@revolist/revogrid 4.22.1 → 4.23.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/cjs/{cell-renderer-BQdEGQXP.js → cell-renderer-DWJ9Px9f.js} +9 -3
- package/dist/cjs/{column.drag.plugin-RDjQhKCH.js → column.drag.plugin-CaEBDG-Q.js} +391 -256
- package/dist/cjs/{column.service-DXYMehqK.js → column.service-f612L4ql.js} +1 -1
- package/dist/cjs/{dimension.helpers-CiiNnlLa.js → dimension.helpers-B9HgANnM.js} +14 -145
- package/dist/cjs/{edit.utils-CecCfA4E.js → edit.utils-pKeiYFLJ.js} +1 -1
- package/dist/cjs/{header-cell-renderer-DGyBrK8I.js → header-cell-renderer-4yq9_WbM.js} +1 -1
- package/dist/cjs/index-DxaSE5uZ.js +136 -0
- package/dist/cjs/index.cjs.js +37 -32
- package/dist/cjs/revo-grid.cjs.entry.js +35 -15
- package/dist/cjs/revogr-attribution_7.cjs.entry.js +43 -25
- package/dist/cjs/revogr-clipboard_3.cjs.entry.js +10 -8
- package/dist/cjs/revogr-data_4.cjs.entry.js +26 -17
- package/dist/cjs/revogr-filter-panel.cjs.entry.js +2 -1
- package/dist/cjs/{text-editor-DnLZW1a-.js → text-editor-B4W-m-r-.js} +3 -3
- package/dist/cjs/{throttle-CfgQFkfR.js → throttle-BCwEuJJq.js} +59 -24
- package/dist/cjs/viewport.helpers-BND76K2j.js +140 -0
- package/dist/cjs/{viewport.store-q6YdR9mg.js → viewport.store-BlKQ4x9H.js} +16 -16
- package/dist/collection/components/data/revogr-data.js +5 -3
- package/dist/collection/components/header/header-group-renderer.js +1 -1
- package/dist/collection/components/header/header-renderer.js +1 -1
- package/dist/collection/components/header/revogr-header-style.css +13 -3
- package/dist/collection/components/header/revogr-header.js +5 -2
- package/dist/collection/components/order/order-row.service.js +6 -5
- package/dist/collection/components/overlay/keyboard.service.js +23 -1
- package/dist/collection/components/overlay/selection.utils.js +8 -6
- package/dist/collection/components/revoGrid/revo-grid.js +6 -5
- package/dist/collection/components/revoGrid/viewport.service.js +2 -1
- package/dist/collection/components/scroll/revogr-viewport-scroll.js +10 -6
- package/dist/collection/components/scrollable/revogr-scroll-virtual.js +4 -10
- package/dist/collection/plugins/filter/filter.panel.js +2 -1
- package/dist/collection/plugins/filter/filter.plugin.js +11 -4
- package/dist/collection/plugins/groupingRow/grouping.row.plugin.js +25 -1
- package/dist/collection/plugins/moveColumn/column.drag.plugin.js +4 -4
- package/dist/collection/plugins/sorting/sorting.func.js +173 -15
- package/dist/collection/plugins/sorting/sorting.plugin.js +167 -84
- package/dist/collection/plugins/sorting/sorting.sign.js +7 -1
- package/dist/collection/serve/controller.js +98 -37
- package/dist/collection/serve/data.js +273 -144
- package/dist/collection/services/dimension.provider.js +16 -1
- package/dist/collection/services/local.scroll.service.js +59 -24
- package/dist/collection/services/scroll.dimension.helpers.js +83 -0
- package/dist/collection/services/selection.store.connector.js +4 -1
- package/dist/collection/store/dimension/dimension.recalculate.plugin.js +22 -9
- package/dist/collection/store/dimension/dimension.store.js +4 -2
- package/dist/collection/store/vp/viewport.helpers.js +9 -0
- package/dist/collection/store/vp/viewport.store.js +5 -16
- package/dist/collection/utils/store.utils.js +3 -3
- package/dist/{revo-grid/cell-renderer-CALsEsnh.js → esm/cell-renderer-8UiGd-s7.js} +9 -3
- package/dist/esm/{column.drag.plugin-Dy5ztusn.js → column.drag.plugin-BsfhsfmB.js} +388 -255
- package/dist/esm/{column.service-CCvAi5l4.js → column.service-DbpulTog.js} +1 -1
- package/dist/{revo-grid/debounce-BfO9dz9v.js → esm/debounce-PCRWZliA.js} +1 -1
- package/dist/{revo-grid/dimension.helpers-DmIvjIa7.js → esm/dimension.helpers-CGKwSvw6.js} +7 -128
- package/dist/esm/{edit.utils-DYN6XZh8.js → edit.utils-Dnnbd0xG.js} +1 -1
- package/dist/{revo-grid/header-cell-renderer-DU8wKAbg.js → esm/header-cell-renderer-DGI2FAD8.js} +1 -1
- package/dist/esm/index-Db3qZoW5.js +127 -0
- package/dist/esm/index.js +11 -10
- package/dist/esm/revo-grid.entry.js +34 -14
- package/dist/esm/revogr-attribution_7.entry.js +42 -24
- package/dist/esm/revogr-clipboard_3.entry.js +11 -9
- package/dist/esm/revogr-data_4.entry.js +27 -18
- package/dist/esm/revogr-filter-panel.entry.js +3 -2
- package/dist/esm/{text-editor-DpCnd6Fq.js → text-editor-C3RUSwH5.js} +2 -2
- package/dist/esm/{throttle-ERvyruXb.js → throttle-CaUDyxyU.js} +60 -25
- package/dist/esm/viewport.helpers-CoCAvmZs.js +133 -0
- package/dist/{revo-grid/viewport.store-CFjDW-3l.js → esm/viewport.store-COAfzAyu.js} +15 -17
- package/dist/{esm/cell-renderer-CALsEsnh.js → revo-grid/cell-renderer-8UiGd-s7.js} +9 -3
- package/dist/revo-grid/{column.drag.plugin-Dy5ztusn.js → column.drag.plugin-BsfhsfmB.js} +388 -255
- package/dist/revo-grid/{column.service-CCvAi5l4.js → column.service-DbpulTog.js} +1 -1
- package/dist/{esm/debounce-BfO9dz9v.js → revo-grid/debounce-PCRWZliA.js} +1 -1
- package/dist/{esm/dimension.helpers-DmIvjIa7.js → revo-grid/dimension.helpers-CGKwSvw6.js} +7 -128
- package/dist/revo-grid/{edit.utils-DYN6XZh8.js → edit.utils-Dnnbd0xG.js} +1 -1
- package/dist/{esm/header-cell-renderer-DU8wKAbg.js → revo-grid/header-cell-renderer-DGI2FAD8.js} +1 -1
- package/dist/revo-grid/index-Db3qZoW5.js +127 -0
- package/dist/revo-grid/index.esm.js +11 -10
- package/dist/revo-grid/revo-grid.entry.js +34 -14
- package/dist/revo-grid/revogr-attribution_7.entry.js +42 -24
- package/dist/revo-grid/revogr-clipboard_3.entry.js +11 -9
- package/dist/revo-grid/revogr-data_4.entry.js +27 -18
- package/dist/revo-grid/revogr-filter-panel.entry.js +3 -2
- package/dist/revo-grid/{text-editor-DpCnd6Fq.js → text-editor-C3RUSwH5.js} +2 -2
- package/dist/revo-grid/{throttle-ERvyruXb.js → throttle-CaUDyxyU.js} +60 -25
- package/dist/revo-grid/viewport.helpers-CoCAvmZs.js +133 -0
- package/dist/{esm/viewport.store-CFjDW-3l.js → revo-grid/viewport.store-COAfzAyu.js} +15 -17
- package/dist/types/components/header/header-group-renderer.d.ts +1 -0
- package/dist/types/components/header/header-renderer.d.ts +1 -0
- package/dist/types/components/overlay/keyboard.service.d.ts +5 -0
- package/dist/types/plugins/groupingRow/grouping.row.plugin.d.ts +8 -0
- package/dist/types/plugins/sorting/sorting.func.d.ts +25 -2
- package/dist/types/plugins/sorting/sorting.plugin.d.ts +84 -9
- package/dist/types/plugins/sorting/sorting.sign.d.ts +5 -1
- package/dist/types/plugins/sorting/sorting.types.d.ts +46 -1
- package/dist/types/services/local.scroll.service.d.ts +10 -2
- package/dist/types/services/scroll.dimension.helpers.d.ts +20 -0
- package/dist/types/store/vp/viewport.helpers.d.ts +2 -0
- package/dist/types/types/interfaces.d.ts +11 -0
- package/hydrate/index.js +649 -365
- package/hydrate/index.mjs +649 -365
- package/package.json +1 -1
- package/standalone/column.service.js +1 -1
- package/standalone/data.store.js +1 -1
- package/standalone/debounce.js +1 -1
- package/standalone/dimension.helpers.js +1 -1
- package/standalone/index.js +1 -1
- package/standalone/local.scroll.timer.js +1 -1
- package/standalone/revo-grid.js +1 -1
- package/standalone/revogr-data2.js +1 -1
- package/standalone/revogr-filter-panel.js +1 -1
- package/standalone/revogr-header2.js +1 -1
- package/standalone/revogr-order-editor2.js +1 -1
- package/standalone/revogr-overlay-selection2.js +1 -1
- package/standalone/revogr-row-headers.js +1 -1
- package/standalone/revogr-row-headers2.js +1 -1
- package/standalone/revogr-scroll-virtual2.js +1 -1
- package/standalone/revogr-viewport-scroll2.js +1 -1
- package/standalone/selection.utils.js +1 -1
- package/standalone/throttle.js +1 -1
- package/standalone/toNumber.js +1 -1
- package/dist/cjs/viewport.helpers-BAovztDd.js +0 -58
- package/dist/esm/viewport.helpers-VXhsJZtn.js +0 -52
- package/dist/revo-grid/viewport.helpers-VXhsJZtn.js +0 -52
|
@@ -1,13 +1,177 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Built by Revolist OU ❤️
|
|
3
3
|
*/
|
|
4
|
+
import { GROUP_COLUMN_PROP } from "../groupingRow/grouping.const";
|
|
4
5
|
import { isGrouping } from "../groupingRow/grouping.service";
|
|
5
6
|
import { getCellRaw } from "../../utils/column.utils";
|
|
6
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Checks whether a sorting map contains at least one active order.
|
|
9
|
+
*
|
|
10
|
+
* Empty maps and properties with `undefined` order are treated as inactive.
|
|
11
|
+
*/
|
|
12
|
+
export function hasActiveSorting(sorting) {
|
|
13
|
+
for (const prop of Object.keys(sorting || {})) {
|
|
14
|
+
if (sorting === null || sorting === void 0 ? void 0 : sorting[prop]) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Compares column properties after object-key coercion.
|
|
22
|
+
*/
|
|
23
|
+
function isSameColumnProp(a, b) {
|
|
24
|
+
return String(a) === String(b);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Returns active sorting properties in explicit priority order.
|
|
28
|
+
*/
|
|
29
|
+
function getActiveSortingProps(sorting, sortingOrder) {
|
|
30
|
+
const activeProps = [];
|
|
31
|
+
const add = (prop) => {
|
|
32
|
+
if ((sorting === null || sorting === void 0 ? void 0 : sorting[prop]) && !activeProps.some(active => isSameColumnProp(active, prop))) {
|
|
33
|
+
activeProps.push(prop);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
sortingOrder === null || sortingOrder === void 0 ? void 0 : sortingOrder.forEach(add);
|
|
37
|
+
Object.keys(sorting || {}).forEach(add);
|
|
38
|
+
return activeProps;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Returns one-based additive sorting rank for a column.
|
|
42
|
+
*
|
|
43
|
+
* A single active sort does not need a visible rank, so it returns undefined.
|
|
44
|
+
*/
|
|
45
|
+
export function getSortingIndex(sorting, prop, sortingOrder) {
|
|
46
|
+
const activeProps = getActiveSortingProps(sorting, sortingOrder);
|
|
47
|
+
if (activeProps.length <= 1) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
const index = activeProps.findIndex(active => isSameColumnProp(active, prop));
|
|
51
|
+
return index >= 0 ? index + 1 : undefined;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Collects only active comparator functions from a sorting function map.
|
|
55
|
+
*
|
|
56
|
+
* This keeps undefined comparator entries from triggering sorting work.
|
|
57
|
+
*/
|
|
58
|
+
function activeSortingEntries(sortingFunc = {}, sortingOrder) {
|
|
59
|
+
const entries = [];
|
|
60
|
+
const add = (prop) => {
|
|
61
|
+
const cmp = sortingFunc[prop];
|
|
62
|
+
if (typeof cmp === 'function' && !entries.some(([active]) => isSameColumnProp(active, prop))) {
|
|
63
|
+
entries.push([prop, cmp]);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
sortingOrder === null || sortingOrder === void 0 ? void 0 : sortingOrder.forEach(add);
|
|
67
|
+
Object.keys(sortingFunc).forEach(add);
|
|
68
|
+
return entries;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Reads and normalizes a value for the built-in default comparer.
|
|
72
|
+
*/
|
|
73
|
+
function getDefaultCompareValue(item, prop, column) {
|
|
74
|
+
const aRaw = column ? getCellRaw(item, column) : item === null || item === void 0 ? void 0 : item[prop];
|
|
75
|
+
return typeof aRaw === 'number' ? aRaw : aRaw === null || aRaw === void 0 ? void 0 : aRaw.toString().toLowerCase();
|
|
76
|
+
}
|
|
77
|
+
function isEmptyCompareValue(value) {
|
|
78
|
+
return value === '' || value === null || value === undefined;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Compares two already-normalized default comparer values.
|
|
82
|
+
*/
|
|
83
|
+
function compareValues(av, bv) {
|
|
84
|
+
if (av === bv) {
|
|
85
|
+
return 0;
|
|
86
|
+
}
|
|
87
|
+
const aEmpty = isEmptyCompareValue(av);
|
|
88
|
+
const bEmpty = isEmptyCompareValue(bv);
|
|
89
|
+
if (aEmpty || bEmpty) {
|
|
90
|
+
if (aEmpty && bEmpty) {
|
|
91
|
+
return 0;
|
|
92
|
+
}
|
|
93
|
+
return aEmpty ? -1 : 1;
|
|
94
|
+
}
|
|
95
|
+
if (av > bv) {
|
|
96
|
+
return 1;
|
|
97
|
+
}
|
|
98
|
+
return -1;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Sorts indexes by precomputed values for default column comparers.
|
|
102
|
+
*
|
|
103
|
+
* This avoids repeatedly parsing the same cell value during large default
|
|
104
|
+
* sorts while preserving normal multi-column ordering.
|
|
105
|
+
*/
|
|
106
|
+
function sortIndexByDefaultComparers(indexes, source, entries, sorting, sortingColumns) {
|
|
107
|
+
const prepared = entries.map(([prop]) => {
|
|
108
|
+
const values = [];
|
|
109
|
+
const column = sortingColumns[prop];
|
|
110
|
+
for (const index of indexes) {
|
|
111
|
+
values[index] = getDefaultCompareValue(source[index], prop, column);
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
order: sorting[prop],
|
|
115
|
+
values,
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
return indexes.sort((a, b) => {
|
|
119
|
+
for (const { order, values } of prepared) {
|
|
120
|
+
const sorted = compareValues(values[a], values[b]);
|
|
121
|
+
if (sorted) {
|
|
122
|
+
return order === 'desc' ? -sorted : sorted;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return 0;
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Detects whether the optimized default-comparer path can be used.
|
|
130
|
+
*
|
|
131
|
+
* Grouped rows and custom `cellCompare` functions stay on the legacy
|
|
132
|
+
* comparator path to preserve their exact behavior.
|
|
133
|
+
*/
|
|
134
|
+
function canUseDefaultCompareFastPath(entries, indexes, source, sorting, sortingColumns) {
|
|
135
|
+
return !indexes.some(index => isGrouping(source[index])) && !!sorting && !!sortingColumns && entries.every(([prop]) => {
|
|
136
|
+
const order = sorting[prop];
|
|
137
|
+
const column = sortingColumns[prop];
|
|
138
|
+
return !!order && !(column === null || column === void 0 ? void 0 : column.cellCompare);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Group placeholder rows are generated for their grouping column. If sorting is
|
|
143
|
+
* requested for another column, the grouped source must be unwrapped first.
|
|
144
|
+
*/
|
|
145
|
+
function hasGroupingRowsForOtherSorting(entries, indexes, source) {
|
|
146
|
+
return indexes.some(index => {
|
|
147
|
+
const item = source[index];
|
|
148
|
+
return isGrouping(item) && !entries.some(([prop]) => isSameColumnProp(item[GROUP_COLUMN_PROP], prop));
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Sorts row indexes against a source collection.
|
|
153
|
+
*
|
|
154
|
+
* @param indexes - Current proxy row indexes to sort.
|
|
155
|
+
* @param source - Full source collection addressed by the indexes.
|
|
156
|
+
* @param sortingFunc - Comparator functions by column property.
|
|
157
|
+
* @param sorting - Active sorting order by column property.
|
|
158
|
+
* @param sortingColumns - Column metadata by property for default-comparer optimization.
|
|
159
|
+
* @param sortingOrder - Active sorting priority in click/config insertion order.
|
|
160
|
+
* @returns Sorted proxy indexes. With no sorting function keys, returns source-order indexes.
|
|
161
|
+
*/
|
|
162
|
+
export function sortIndexByItems(indexes, source, sortingFunc = {}, sorting, sortingColumns, sortingOrder) {
|
|
163
|
+
const hasSortingKeys = Object.keys(sortingFunc).length > 0;
|
|
164
|
+
const sortingEntries = activeSortingEntries(sortingFunc, sortingOrder);
|
|
7
165
|
// if no sorting - return unsorted indexes
|
|
8
|
-
if (
|
|
166
|
+
if (sortingEntries.length === 0) {
|
|
9
167
|
// Unsorted indexes
|
|
10
|
-
return [...Array(indexes.length).keys()];
|
|
168
|
+
return hasSortingKeys ? indexes : [...new Array(indexes.length).keys()];
|
|
169
|
+
}
|
|
170
|
+
if (hasGroupingRowsForOtherSorting(sortingEntries, indexes, source)) {
|
|
171
|
+
return indexes;
|
|
172
|
+
}
|
|
173
|
+
if (canUseDefaultCompareFastPath(sortingEntries, indexes, source, sorting, sortingColumns)) {
|
|
174
|
+
return sortIndexByDefaultComparers(indexes, source, sortingEntries, sorting, sortingColumns);
|
|
11
175
|
}
|
|
12
176
|
//
|
|
13
177
|
/**
|
|
@@ -17,15 +181,15 @@ export function sortIndexByItems(indexes, source, sortingFunc = {}) {
|
|
|
17
181
|
return indexes.sort((a, b) => {
|
|
18
182
|
const itemA = source[a];
|
|
19
183
|
const itemB = source[b];
|
|
20
|
-
for (const [prop, cmp] of
|
|
184
|
+
for (const [prop, cmp] of sortingEntries) {
|
|
21
185
|
if (isGrouping(itemA)) {
|
|
22
|
-
if (itemA[
|
|
23
|
-
return
|
|
186
|
+
if (!isSameColumnProp(itemA[GROUP_COLUMN_PROP], prop)) {
|
|
187
|
+
return a - b;
|
|
24
188
|
}
|
|
25
189
|
}
|
|
26
190
|
if (isGrouping(itemB)) {
|
|
27
|
-
if (itemB[
|
|
28
|
-
return
|
|
191
|
+
if (!isSameColumnProp(itemB[GROUP_COLUMN_PROP], prop)) {
|
|
192
|
+
return a - b;
|
|
29
193
|
}
|
|
30
194
|
}
|
|
31
195
|
/**
|
|
@@ -45,13 +209,7 @@ export function defaultCellCompare(prop, a, b) {
|
|
|
45
209
|
const bRaw = this.column ? getCellRaw(b, this.column) : b === null || b === void 0 ? void 0 : b[prop];
|
|
46
210
|
const av = typeof aRaw === 'number' ? aRaw : aRaw === null || aRaw === void 0 ? void 0 : aRaw.toString().toLowerCase();
|
|
47
211
|
const bv = typeof bRaw === 'number' ? bRaw : bRaw === null || bRaw === void 0 ? void 0 : bRaw.toString().toLowerCase();
|
|
48
|
-
|
|
49
|
-
return 0;
|
|
50
|
-
}
|
|
51
|
-
if (av > bv) {
|
|
52
|
-
return 1;
|
|
53
|
-
}
|
|
54
|
-
return -1;
|
|
212
|
+
return compareValues(av, bv);
|
|
55
213
|
}
|
|
56
214
|
export function descCellCompare(cmp) {
|
|
57
215
|
return (prop, a, b) => {
|
|
@@ -1,15 +1,30 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Built by Revolist OU ❤️
|
|
3
3
|
*/
|
|
4
|
-
import size from "lodash/size";
|
|
5
4
|
import debounce from "lodash/debounce";
|
|
6
5
|
import { BasePlugin } from "../base.plugin";
|
|
7
6
|
import { getColumnByProp } from "../../utils/column.utils";
|
|
8
7
|
import { columnTypes, rowTypes } from "../../store/index";
|
|
9
|
-
import {
|
|
8
|
+
import { isGrouping } from "../groupingRow/grouping.service";
|
|
9
|
+
import { getComparer, getNextOrder, getSortingIndex, hasActiveSorting, sortIndexByItems, } from "./sorting.func";
|
|
10
10
|
export * from './sorting.types';
|
|
11
11
|
export * from './sorting.func';
|
|
12
12
|
export * from './sorting.sign';
|
|
13
|
+
function getSortableRowIndexes(indexes, source) {
|
|
14
|
+
return indexes.filter(index => !isGrouping(source[index]));
|
|
15
|
+
}
|
|
16
|
+
function mergeSortedRowsWithGroups(indexes, source, sortedRows) {
|
|
17
|
+
if (sortedRows.length === indexes.length) {
|
|
18
|
+
return sortedRows;
|
|
19
|
+
}
|
|
20
|
+
let rowIndex = 0;
|
|
21
|
+
return indexes.map(index => {
|
|
22
|
+
if (isGrouping(source[index])) {
|
|
23
|
+
return index;
|
|
24
|
+
}
|
|
25
|
+
return sortedRows[rowIndex++];
|
|
26
|
+
});
|
|
27
|
+
}
|
|
13
28
|
/**
|
|
14
29
|
* Lifecycle
|
|
15
30
|
* 1. @event `beforesorting` - Triggered when sorting just starts. Nothing has happened yet. This can be triggered from a column or from the source. If the type is from rows, the column will be undefined.
|
|
@@ -24,54 +39,37 @@ export class SortingPlugin extends BasePlugin {
|
|
|
24
39
|
super(revogrid, providers);
|
|
25
40
|
this.revogrid = revogrid;
|
|
26
41
|
/**
|
|
27
|
-
* Delayed sorting promise
|
|
42
|
+
* Delayed sorting promise registered in the grid render job queue.
|
|
28
43
|
*/
|
|
29
44
|
this.sortingPromise = null;
|
|
30
45
|
/**
|
|
31
|
-
*
|
|
46
|
+
* Debounced sorting entry point.
|
|
47
|
+
*
|
|
48
|
+
* Sorting can be requested by column changes, source changes, and header
|
|
49
|
+
* clicks in quick succession, so the actual sort is delayed and coalesced.
|
|
32
50
|
*/
|
|
33
|
-
this.postponeSort = debounce((order, comparison, ignoreViewportUpdate) => this.runSorting(order, comparison, ignoreViewportUpdate), 50);
|
|
34
|
-
|
|
35
|
-
var _a;
|
|
36
|
-
if (cfg) {
|
|
37
|
-
const sortingFunc = {};
|
|
38
|
-
const order = {};
|
|
39
|
-
(_a = cfg.columns) === null || _a === void 0 ? void 0 : _a.forEach(col => {
|
|
40
|
-
sortingFunc[col.prop] = getComparer(col, col.order);
|
|
41
|
-
order[col.prop] = col.order;
|
|
42
|
-
});
|
|
43
|
-
if (cfg.additive) {
|
|
44
|
-
this.sorting = Object.assign(Object.assign({}, this.sorting), order);
|
|
45
|
-
this.sortingFunc = Object.assign(Object.assign({}, this.sortingFunc), sortingFunc);
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
// // set sorting
|
|
49
|
-
this.sorting = order;
|
|
50
|
-
this.sortingFunc = sortingFunc;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
setConfig(config);
|
|
51
|
+
this.postponeSort = debounce((order, comparison, sortingColumns, sortingOrder, ignoreViewportUpdate) => this.runSorting(order, comparison, sortingColumns, sortingOrder, ignoreViewportUpdate), 50);
|
|
52
|
+
this.applySortingConfig(config);
|
|
55
53
|
this.addEventListener('sortingconfigchanged', ({ detail }) => {
|
|
56
54
|
config = detail;
|
|
57
|
-
|
|
58
|
-
this.startSorting(this.sorting, this.sortingFunc);
|
|
55
|
+
this.applySortingConfig(detail);
|
|
56
|
+
this.startSorting(this.sorting, this.sortingFunc, this.sortingColumns, this.sortingOrder);
|
|
59
57
|
});
|
|
60
58
|
this.addEventListener('beforeheaderrender', ({ detail, }) => {
|
|
61
59
|
var _a;
|
|
62
60
|
const { data: column } = detail;
|
|
63
61
|
if (column.sortable) {
|
|
64
|
-
detail.data = Object.assign(Object.assign({}, column), { order: (_a = this.sorting) === null || _a === void 0 ? void 0 : _a[column.prop] });
|
|
62
|
+
detail.data = Object.assign(Object.assign({}, column), { order: (_a = this.sorting) === null || _a === void 0 ? void 0 : _a[column.prop], sortIndex: getSortingIndex(this.sorting, column.prop, this.sortingOrder) });
|
|
65
63
|
}
|
|
66
64
|
});
|
|
67
65
|
this.addEventListener('beforeanysource', ({ detail: { type }, }) => {
|
|
68
66
|
// if sorting was provided - sort data
|
|
69
|
-
if (
|
|
67
|
+
if (hasActiveSorting(this.sorting) && this.sortingFunc) {
|
|
70
68
|
const event = this.emit('beforesourcesortingapply', { type, sorting: this.sorting });
|
|
71
69
|
if (event.defaultPrevented) {
|
|
72
70
|
return;
|
|
73
71
|
}
|
|
74
|
-
this.startSorting(this.sorting, this.sortingFunc);
|
|
72
|
+
this.startSorting(this.sorting, this.sortingFunc, this.sortingColumns, this.sortingOrder);
|
|
75
73
|
}
|
|
76
74
|
});
|
|
77
75
|
this.addEventListener('aftercolumnsset', ({ detail: { order }, }) => {
|
|
@@ -81,13 +79,24 @@ export class SortingPlugin extends BasePlugin {
|
|
|
81
79
|
}
|
|
82
80
|
const columns = this.providers.column.getColumns();
|
|
83
81
|
const sortingFunc = {};
|
|
82
|
+
const sortingColumns = {};
|
|
83
|
+
const sortingOrder = [];
|
|
84
|
+
const sorting = {};
|
|
84
85
|
for (let prop in order) {
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
if (order[prop]) {
|
|
87
|
+
const column = getColumnByProp(columns, prop);
|
|
88
|
+
const cmp = getComparer(column, order[prop]);
|
|
89
|
+
sorting[prop] = order[prop];
|
|
90
|
+
sortingFunc[prop] = cmp;
|
|
91
|
+
sortingColumns[prop] = column;
|
|
92
|
+
sortingOrder.push(prop);
|
|
93
|
+
}
|
|
87
94
|
}
|
|
88
95
|
// set sorting
|
|
89
|
-
this.sorting =
|
|
90
|
-
this.sortingFunc =
|
|
96
|
+
this.sorting = hasActiveSorting(sorting) ? sorting : undefined;
|
|
97
|
+
this.sortingFunc = this.sorting ? sortingFunc : undefined;
|
|
98
|
+
this.sortingColumns = this.sorting ? sortingColumns : undefined;
|
|
99
|
+
this.sortingOrder = this.sorting ? sortingOrder : undefined;
|
|
91
100
|
});
|
|
92
101
|
this.addEventListener('beforeheaderclick', (e) => {
|
|
93
102
|
var _a, _b, _c, _d;
|
|
@@ -101,23 +110,89 @@ export class SortingPlugin extends BasePlugin {
|
|
|
101
110
|
});
|
|
102
111
|
}
|
|
103
112
|
/**
|
|
104
|
-
*
|
|
113
|
+
* Creates mutable sorting maps from current state when additive sorting is requested.
|
|
114
|
+
*/
|
|
115
|
+
createSortingState(additive) {
|
|
116
|
+
var _a;
|
|
117
|
+
return {
|
|
118
|
+
sorting: additive ? Object.assign({}, this.sorting) : {},
|
|
119
|
+
sortingFunc: additive ? Object.assign({}, this.sortingFunc) : {},
|
|
120
|
+
sortingColumns: additive ? Object.assign({}, this.sortingColumns) : {},
|
|
121
|
+
sortingOrder: additive ? [...((_a = this.sortingOrder) !== null && _a !== void 0 ? _a : [])] : [],
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Stores normalized sorting state, clearing inactive empty maps.
|
|
126
|
+
*/
|
|
127
|
+
setSortingState({ sorting, sortingFunc, sortingColumns, sortingOrder, }) {
|
|
128
|
+
this.sorting = hasActiveSorting(sorting) ? sorting : undefined;
|
|
129
|
+
this.sortingFunc = this.sorting ? sortingFunc : undefined;
|
|
130
|
+
this.sortingColumns = this.sorting ? sortingColumns : undefined;
|
|
131
|
+
this.sortingOrder = this.sorting ? sortingOrder : undefined;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Adds or replaces a column in a sorting state.
|
|
105
135
|
*/
|
|
106
|
-
|
|
136
|
+
setColumnSorting(state, prop, order, cmp, column) {
|
|
137
|
+
state.sorting[prop] = order;
|
|
138
|
+
state.sortingFunc[prop] = cmp;
|
|
139
|
+
state.sortingColumns[prop] = column;
|
|
140
|
+
if (!state.sortingOrder.some(sortingProp => String(sortingProp) === String(prop))) {
|
|
141
|
+
state.sortingOrder.push(prop);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Removes a column from a sorting state.
|
|
146
|
+
*/
|
|
147
|
+
clearColumnSorting(state, prop) {
|
|
148
|
+
delete state.sorting[prop];
|
|
149
|
+
delete state.sortingFunc[prop];
|
|
150
|
+
delete state.sortingColumns[prop];
|
|
151
|
+
const index = state.sortingOrder.findIndex(sortingProp => String(sortingProp) === String(prop));
|
|
152
|
+
if (index >= 0) {
|
|
153
|
+
state.sortingOrder.splice(index, 1);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Normalizes external sorting configuration into internal order,
|
|
158
|
+
* comparator, and column metadata maps.
|
|
159
|
+
*/
|
|
160
|
+
applySortingConfig(cfg) {
|
|
161
|
+
var _a;
|
|
162
|
+
if (!cfg) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const state = this.createSortingState(cfg.additive);
|
|
166
|
+
(_a = cfg.columns) === null || _a === void 0 ? void 0 : _a.forEach(col => {
|
|
167
|
+
if (col.order) {
|
|
168
|
+
this.setColumnSorting(state, col.prop, col.order, getComparer(col, col.order), col);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
this.clearColumnSorting(state, col.prop);
|
|
172
|
+
});
|
|
173
|
+
this.setSortingState(state);
|
|
174
|
+
}
|
|
175
|
+
startSorting(order, sortingFunc, sortingColumns, sortingOrder, ignoreViewportUpdate) {
|
|
107
176
|
if (!this.sortingPromise) {
|
|
108
177
|
// add job before render
|
|
109
178
|
this.revogrid.jobsBeforeRender.push(new Promise(resolve => {
|
|
110
179
|
this.sortingPromise = resolve;
|
|
111
180
|
}));
|
|
112
181
|
}
|
|
113
|
-
|
|
182
|
+
if (typeof sortingColumns === 'boolean') {
|
|
183
|
+
this.postponeSort(order, sortingFunc, undefined, undefined, sortingColumns);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
this.postponeSort(order, sortingFunc, sortingColumns, sortingOrder, ignoreViewportUpdate);
|
|
114
187
|
}
|
|
115
188
|
/**
|
|
116
|
-
*
|
|
117
|
-
*
|
|
189
|
+
* Applies sorting requested by a sortable header click.
|
|
190
|
+
*
|
|
191
|
+
* @param column - Column that initiated sorting.
|
|
192
|
+
* @param additive - If true, add/remove this column from the current multi-sort state.
|
|
118
193
|
*/
|
|
119
194
|
headerclick(column, additive) {
|
|
120
|
-
var _a
|
|
195
|
+
var _a;
|
|
121
196
|
const columnProp = column.prop;
|
|
122
197
|
let order = getNextOrder((_a = this.sorting) === null || _a === void 0 ? void 0 : _a[columnProp]);
|
|
123
198
|
const beforeEvent = this.emit('beforesorting', { column, order, additive });
|
|
@@ -135,52 +210,59 @@ export class SortingPlugin extends BasePlugin {
|
|
|
135
210
|
return;
|
|
136
211
|
}
|
|
137
212
|
const cmp = getComparer(beforeApplyEvent.detail.column, beforeApplyEvent.detail.order);
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
213
|
+
this.applyHeaderSorting(beforeApplyEvent.detail.column, beforeApplyEvent.detail.additive, order, cmp);
|
|
214
|
+
this.startSorting(this.sorting, this.sortingFunc, this.sortingColumns, this.sortingOrder);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Applies sorting state produced by a header click.
|
|
218
|
+
*/
|
|
219
|
+
applyHeaderSorting(column, additive, order, cmp) {
|
|
220
|
+
if (!additive) {
|
|
221
|
+
this.setSortingState(order ? {
|
|
222
|
+
sorting: { [column.prop]: order },
|
|
223
|
+
sortingFunc: { [column.prop]: cmp },
|
|
224
|
+
sortingColumns: { [column.prop]: column },
|
|
225
|
+
sortingOrder: [column.prop],
|
|
226
|
+
} : this.createSortingState());
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
const state = this.createSortingState(true);
|
|
230
|
+
if (order) {
|
|
231
|
+
this.setColumnSorting(state, column.prop, order, cmp, column);
|
|
152
232
|
}
|
|
153
233
|
else {
|
|
154
|
-
|
|
155
|
-
// reset sorting
|
|
156
|
-
this.sorting = { [columnProp]: order };
|
|
157
|
-
this.sortingFunc = { [columnProp]: cmp };
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
(_b = this.sorting) === null || _b === void 0 ? true : delete _b[columnProp];
|
|
161
|
-
(_c = this.sortingFunc) === null || _c === void 0 ? true : delete _c[columnProp];
|
|
162
|
-
}
|
|
234
|
+
this.clearColumnSorting(state, column.prop);
|
|
163
235
|
}
|
|
164
|
-
this.
|
|
236
|
+
this.setSortingState(state);
|
|
165
237
|
}
|
|
166
|
-
runSorting(order, comparison, ignoreViewportUpdate) {
|
|
167
|
-
var _a;
|
|
168
|
-
|
|
169
|
-
|
|
238
|
+
runSorting(order, comparison, sortingColumns, sortingOrder, ignoreViewportUpdate) {
|
|
239
|
+
var _a, _b;
|
|
240
|
+
if (typeof sortingColumns === 'boolean') {
|
|
241
|
+
this.sort(order, comparison, undefined, undefined, undefined, sortingColumns);
|
|
242
|
+
(_a = this.sortingPromise) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
243
|
+
this.sortingPromise = null;
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
this.sort(order, comparison, sortingColumns, sortingOrder, undefined, ignoreViewportUpdate);
|
|
247
|
+
(_b = this.sortingPromise) === null || _b === void 0 ? void 0 : _b.call(this);
|
|
170
248
|
this.sortingPromise = null;
|
|
171
249
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
250
|
+
sort(sorting, sortingFunc, sortingColumns, sortingOrder, types = rowTypes, ignoreViewportUpdate = false) {
|
|
251
|
+
let activeSortingColumns;
|
|
252
|
+
let activeSortingOrder;
|
|
253
|
+
let activeTypes = types;
|
|
254
|
+
let activeIgnoreViewportUpdate = ignoreViewportUpdate;
|
|
255
|
+
if (Array.isArray(sortingColumns)) {
|
|
256
|
+
activeTypes = sortingColumns;
|
|
257
|
+
activeIgnoreViewportUpdate = typeof sortingOrder === 'boolean' ? sortingOrder : false;
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
activeSortingColumns = sortingColumns;
|
|
261
|
+
activeSortingOrder = Array.isArray(sortingOrder) ? sortingOrder : undefined;
|
|
262
|
+
}
|
|
181
263
|
// if no sorting - reset
|
|
182
264
|
if (!Object.keys(sorting || {}).length) {
|
|
183
|
-
for (let type of
|
|
265
|
+
for (let type of activeTypes) {
|
|
184
266
|
const storeService = this.providers.data.stores[type];
|
|
185
267
|
// row data
|
|
186
268
|
const source = storeService.store.get('source');
|
|
@@ -189,26 +271,27 @@ export class SortingPlugin extends BasePlugin {
|
|
|
189
271
|
// row indexes
|
|
190
272
|
const newItemsOrder = Array.from({ length: source.length }, (_, i) => i); // recover indexes range(0, source.length)
|
|
191
273
|
this.providers.dimension.updateSizesPositionByNewDataIndexes(type, newItemsOrder, proxyItems);
|
|
192
|
-
storeService.setData({ proxyItems: newItemsOrder
|
|
274
|
+
storeService.setData({ proxyItems: newItemsOrder });
|
|
193
275
|
}
|
|
194
276
|
}
|
|
195
277
|
else {
|
|
196
|
-
for (let type of
|
|
278
|
+
for (let type of activeTypes) {
|
|
197
279
|
const storeService = this.providers.data.stores[type];
|
|
198
280
|
// row data
|
|
199
281
|
const source = storeService.store.get('source');
|
|
200
282
|
// row indexes
|
|
201
283
|
const proxyItems = storeService.store.get('proxyItems');
|
|
202
|
-
const
|
|
284
|
+
const sortItems = getSortableRowIndexes(proxyItems, source);
|
|
285
|
+
const sortedItems = sortIndexByItems([...sortItems], source, sortingFunc, sorting, activeSortingColumns, activeSortingOrder);
|
|
286
|
+
const newItemsOrder = mergeSortedRowsWithGroups(proxyItems, source, sortedItems);
|
|
203
287
|
// take row indexes before trim applied and proxy items
|
|
204
288
|
const prevItems = storeService.store.get('items');
|
|
205
289
|
storeService.setData({
|
|
206
290
|
proxyItems: newItemsOrder,
|
|
207
|
-
source: [...source],
|
|
208
291
|
});
|
|
209
292
|
// take currently visible row indexes
|
|
210
293
|
const newItems = storeService.store.get('items');
|
|
211
|
-
if (!
|
|
294
|
+
if (!activeIgnoreViewportUpdate) {
|
|
212
295
|
this.providers.dimension
|
|
213
296
|
.updateSizesPositionByNewDataIndexes(type, newItems, prevItems);
|
|
214
297
|
}
|
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
* Built by Revolist OU ❤️
|
|
3
3
|
*/
|
|
4
4
|
import { h } from "@stencil/core";
|
|
5
|
+
/**
|
|
6
|
+
* Renders sorting direction and optional additive sorting rank.
|
|
7
|
+
*/
|
|
5
8
|
export const SortingSign = ({ column }) => {
|
|
6
9
|
var _a;
|
|
7
|
-
|
|
10
|
+
const indicatorAttrs = { class: 'sort-indicator' };
|
|
11
|
+
const iconAttrs = { class: (_a = column === null || column === void 0 ? void 0 : column.order) !== null && _a !== void 0 ? _a : 'sort-off' };
|
|
12
|
+
const orderIndexAttrs = { class: 'sort-order-index' };
|
|
13
|
+
return (h("span", Object.assign({}, indicatorAttrs), h("i", Object.assign({}, iconAttrs)), (column === null || column === void 0 ? void 0 : column.sortIndex) ? (h("sup", Object.assign({}, orderIndexAttrs), column.sortIndex)) : null));
|
|
8
14
|
};
|