@gravity-ui/react-data-table 1.0.3
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/CHANGELOG.md +62 -0
- package/LICENSE +21 -0
- package/README.md +276 -0
- package/build/esm/lib/DataTable.d.ts +455 -0
- package/build/esm/lib/DataTable.js +838 -0
- package/build/esm/lib/DataTable.scss +273 -0
- package/build/esm/lib/constants.d.ts +11 -0
- package/build/esm/lib/constants.js +11 -0
- package/build/esm/lib/featureSupport.d.ts +1 -0
- package/build/esm/lib/featureSupport.js +7 -0
- package/build/esm/lib/height-observer.d.ts +14 -0
- package/build/esm/lib/height-observer.js +40 -0
- package/build/esm/lib/index.d.ts +4 -0
- package/build/esm/lib/index.js +4 -0
- package/build/esm/lib/types.d.ts +111 -0
- package/build/esm/lib/types.js +1 -0
- package/build/esm/lib/util.d.ts +28 -0
- package/build/esm/lib/util.js +146 -0
- package/package.json +102 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--data-table-header-vertical-padding: 5px;
|
|
3
|
+
--data-table-cell-vertical-padding: 5px;
|
|
4
|
+
--data-table-cell-horizontal-padding: 10px;
|
|
5
|
+
--data-table-cell-border-padding: var(--data-table-cell-horizontal-padding);
|
|
6
|
+
--data-table-cell-align: top;
|
|
7
|
+
--data-table-head-align: top;
|
|
8
|
+
--data-table-row-height: 30px;
|
|
9
|
+
--data-table-sort-icon-space: 18px;
|
|
10
|
+
--data-table-sort-icon-opacity-inactive: 0.15;
|
|
11
|
+
--data-table-sort-icon-color: inherit;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
$cell-border: 1px solid var(--data-table-border-color);
|
|
15
|
+
|
|
16
|
+
.data-table {
|
|
17
|
+
$block: &;
|
|
18
|
+
|
|
19
|
+
position: relative;
|
|
20
|
+
box-sizing: border-box;
|
|
21
|
+
|
|
22
|
+
&__box {
|
|
23
|
+
width: 100%;
|
|
24
|
+
height: 100%;
|
|
25
|
+
box-sizing: border-box;
|
|
26
|
+
|
|
27
|
+
&_sticky-head_moving {
|
|
28
|
+
overflow: visible;
|
|
29
|
+
position: relative;
|
|
30
|
+
z-index: 0;
|
|
31
|
+
|
|
32
|
+
#{$block}__th {
|
|
33
|
+
padding-top: 0;
|
|
34
|
+
padding-bottom: 0;
|
|
35
|
+
border-top: 0;
|
|
36
|
+
border-bottom: 0;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
#{$block}__head-cell {
|
|
40
|
+
display: block;
|
|
41
|
+
height: 0;
|
|
42
|
+
overflow: hidden;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
#{$block}__row_header-data {
|
|
46
|
+
visibility: hidden;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
&_sticky-footer_fixed,
|
|
50
|
+
&_sticky-head_fixed {
|
|
51
|
+
overflow: auto;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
&__table {
|
|
56
|
+
border-collapse: collapse;
|
|
57
|
+
table-layout: fixed;
|
|
58
|
+
|
|
59
|
+
&_sticky {
|
|
60
|
+
width: 100%;
|
|
61
|
+
background: var(--data-table-color-base);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
&__row {
|
|
66
|
+
height: var(--data-table-row-height);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
&__th {
|
|
70
|
+
font-weight: 500;
|
|
71
|
+
cursor: default;
|
|
72
|
+
padding: var(--data-table-header-vertical-padding) var(--data-table-cell-horizontal-padding);
|
|
73
|
+
border: $cell-border;
|
|
74
|
+
position: relative;
|
|
75
|
+
text-align: left;
|
|
76
|
+
vertical-align: var(--data-table-head-align);
|
|
77
|
+
|
|
78
|
+
&_sortable {
|
|
79
|
+
cursor: pointer;
|
|
80
|
+
|
|
81
|
+
#{$block}__head-cell {
|
|
82
|
+
padding-right: var(--data-table-sort-icon-space);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
&#{$block}__th_align_right {
|
|
86
|
+
#{$block}__head-cell {
|
|
87
|
+
padding-right: 0;
|
|
88
|
+
padding-left: var(--data-table-sort-icon-space);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
#{$block}__sort-icon {
|
|
92
|
+
left: 0;
|
|
93
|
+
right: auto;
|
|
94
|
+
transform: translate(0, -50%) scaleX(-1);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
&__td {
|
|
101
|
+
padding: var(--data-table-cell-vertical-padding) var(--data-table-cell-horizontal-padding);
|
|
102
|
+
border: $cell-border;
|
|
103
|
+
vertical-align: var(--data-table-cell-align);
|
|
104
|
+
white-space: nowrap;
|
|
105
|
+
overflow: hidden;
|
|
106
|
+
text-overflow: ellipsis;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
&__td,
|
|
110
|
+
&__th {
|
|
111
|
+
&_index {
|
|
112
|
+
text-align: right;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
&_align {
|
|
116
|
+
&_left {
|
|
117
|
+
text-align: left;
|
|
118
|
+
}
|
|
119
|
+
&_center {
|
|
120
|
+
text-align: center;
|
|
121
|
+
}
|
|
122
|
+
&_right {
|
|
123
|
+
text-align: right;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
&:first-child {
|
|
128
|
+
padding-left: var(--data-table-cell-border-padding);
|
|
129
|
+
}
|
|
130
|
+
&:last-child {
|
|
131
|
+
padding-right: var(--data-table-cell-border-padding);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
&__index {
|
|
136
|
+
text-align: right;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
&__head-cell {
|
|
140
|
+
display: inline-block;
|
|
141
|
+
position: relative;
|
|
142
|
+
vertical-align: top;
|
|
143
|
+
white-space: nowrap;
|
|
144
|
+
max-width: 100%;
|
|
145
|
+
box-sizing: border-box;
|
|
146
|
+
overflow: hidden;
|
|
147
|
+
text-overflow: ellipsis;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
&__error {
|
|
151
|
+
padding: 20px;
|
|
152
|
+
white-space: pre-wrap;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
&__sort-icon {
|
|
156
|
+
display: inline-flex;
|
|
157
|
+
position: absolute;
|
|
158
|
+
top: 50%;
|
|
159
|
+
right: 0;
|
|
160
|
+
transform: translate(0, -50%);
|
|
161
|
+
color: var(--data-table-sort-icon-color);
|
|
162
|
+
|
|
163
|
+
&:after {
|
|
164
|
+
content: attr(data-index);
|
|
165
|
+
position: absolute;
|
|
166
|
+
font-size: 8px;
|
|
167
|
+
top: -5px;
|
|
168
|
+
left: 100%;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
&_shadow {
|
|
172
|
+
opacity: var(--data-table-sort-icon-opacity-inactive);
|
|
173
|
+
&:after {
|
|
174
|
+
content: none;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
&__icon {
|
|
180
|
+
vertical-align: top;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
&__no-data {
|
|
184
|
+
background: var(--data-table-color-stripe);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
&__sticky {
|
|
188
|
+
$sticky: &;
|
|
189
|
+
&_fixed {
|
|
190
|
+
position: absolute;
|
|
191
|
+
z-index: 1;
|
|
192
|
+
left: 0;
|
|
193
|
+
right: 0;
|
|
194
|
+
overflow: hidden;
|
|
195
|
+
|
|
196
|
+
&#{$sticky}_head {
|
|
197
|
+
top: 0;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
&#{$sticky}_footer {
|
|
201
|
+
bottom: 0;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
&_moving {
|
|
205
|
+
position: sticky;
|
|
206
|
+
z-index: 1;
|
|
207
|
+
margin-bottom: -1px;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
&_striped-rows {
|
|
212
|
+
#{$block}__row {
|
|
213
|
+
&_odd {
|
|
214
|
+
background: var(--data-table-color-stripe);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
&_highlight-rows {
|
|
220
|
+
#{$block}__row {
|
|
221
|
+
&:hover {
|
|
222
|
+
background: var(--data-table-color-hover-area);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
&_header_multiline {
|
|
228
|
+
#{$block}__head-cell {
|
|
229
|
+
white-space: normal;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
&_header_pre {
|
|
233
|
+
#{$block}__head-cell {
|
|
234
|
+
white-space: pre;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
&__foot {
|
|
239
|
+
background: var(--data-table-color-footer-area);
|
|
240
|
+
|
|
241
|
+
&_has-sticky-footer_moving {
|
|
242
|
+
visibility: hidden;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
&_theme_yandex-cloud {
|
|
247
|
+
--data-table-color-base: var(
|
|
248
|
+
--yc-color-base-background,
|
|
249
|
+
var(--yc-color-base, var(--color-base))
|
|
250
|
+
);
|
|
251
|
+
--data-table-color-stripe: var(
|
|
252
|
+
--yc-color-base-generic-ultralight,
|
|
253
|
+
var(--yc-color-base-area, var(--color-base-area))
|
|
254
|
+
);
|
|
255
|
+
--data-table-border-color: var(
|
|
256
|
+
--yc-color-base-generic-hover,
|
|
257
|
+
var(--yc-color-contrast-15-solid, var(--color-contrast-15-solid))
|
|
258
|
+
);
|
|
259
|
+
--data-table-color-hover-area: var(
|
|
260
|
+
--yc-color-base-simple-hover,
|
|
261
|
+
var(--yc-color-hover-area, var(--color-hover-area))
|
|
262
|
+
);
|
|
263
|
+
--data-table-color-footer-area: var(--data-table-color-base);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
&_theme_legacy {
|
|
267
|
+
--data-table-color-base: #ffffff;
|
|
268
|
+
--data-table-color-stripe: rgba(0, 0, 0, 0.03);
|
|
269
|
+
--data-table-border-color: #dddddd;
|
|
270
|
+
--data-table-color-hover-area: #ffeba0;
|
|
271
|
+
--data-table-color-footer-area: var(--data-table-color-base);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const ASCENDING = 1;
|
|
2
|
+
export declare const DESCENDING = -1;
|
|
3
|
+
export declare const LEFT = "left";
|
|
4
|
+
export declare const CENTER = "center";
|
|
5
|
+
export declare const RIGHT = "right";
|
|
6
|
+
export declare const FIXED = "fixed";
|
|
7
|
+
export declare const MOVING = "moving";
|
|
8
|
+
export declare const LEGACY_THEME = "legacy";
|
|
9
|
+
export declare const YCLOUD_THEME = "yandex-cloud";
|
|
10
|
+
export declare const INDEX_COLUMN = "__index__";
|
|
11
|
+
export declare const UI_TIMEOUT = 500;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const ASCENDING = 1;
|
|
2
|
+
export const DESCENDING = -1;
|
|
3
|
+
export const LEFT = 'left';
|
|
4
|
+
export const CENTER = 'center';
|
|
5
|
+
export const RIGHT = 'right';
|
|
6
|
+
export const FIXED = 'fixed';
|
|
7
|
+
export const MOVING = 'moving';
|
|
8
|
+
export const LEGACY_THEME = 'legacy';
|
|
9
|
+
export const YCLOUD_THEME = 'yandex-cloud';
|
|
10
|
+
export const INDEX_COLUMN = '__index__';
|
|
11
|
+
export const UI_TIMEOUT = 500;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const positionStickySupported: boolean;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
function _positionStickySupported() {
|
|
2
|
+
const el = document.createElement('a');
|
|
3
|
+
const mStyle = el.style;
|
|
4
|
+
mStyle.cssText = 'position:sticky; position:-webkit-sticky;';
|
|
5
|
+
return mStyle.position.indexOf('sticky') !== -1;
|
|
6
|
+
}
|
|
7
|
+
export const positionStickySupported = _positionStickySupported();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface HeightObserverParams {
|
|
2
|
+
getSrcElement: () => HTMLElement | null;
|
|
3
|
+
onHeightChange: (height: number) => void;
|
|
4
|
+
}
|
|
5
|
+
export declare class HeightObserver {
|
|
6
|
+
prevHeight: number;
|
|
7
|
+
params: HeightObserverParams;
|
|
8
|
+
constructor(params: HeightObserverParams);
|
|
9
|
+
destroy(): void;
|
|
10
|
+
get node(): HTMLElement | null;
|
|
11
|
+
checkAndUpdateHeight: () => void;
|
|
12
|
+
updateHeight(height: number): void;
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const defaultParams = {
|
|
2
|
+
getSrcElement: () => null,
|
|
3
|
+
onHeightChange: () => { },
|
|
4
|
+
};
|
|
5
|
+
export class HeightObserver {
|
|
6
|
+
constructor(params) {
|
|
7
|
+
this.prevHeight = 0;
|
|
8
|
+
this.params = defaultParams;
|
|
9
|
+
this.checkAndUpdateHeight = () => {
|
|
10
|
+
if (this.node) {
|
|
11
|
+
requestAnimationFrame(() => {
|
|
12
|
+
const node = this.node;
|
|
13
|
+
if (node) {
|
|
14
|
+
this.updateHeight(node.offsetHeight);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
this.updateHeight(0);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
this.updateHeight(0);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
this.params = Object.assign({}, params);
|
|
26
|
+
}
|
|
27
|
+
destroy() {
|
|
28
|
+
this.updateHeight(0);
|
|
29
|
+
this.params = defaultParams;
|
|
30
|
+
}
|
|
31
|
+
get node() {
|
|
32
|
+
return this.params.getSrcElement();
|
|
33
|
+
}
|
|
34
|
+
updateHeight(height) {
|
|
35
|
+
if (this.prevHeight !== height) {
|
|
36
|
+
this.prevHeight = height;
|
|
37
|
+
this.params.onHeightChange(height);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import ReactList from 'react-list';
|
|
3
|
+
import { ASCENDING, CENTER, DESCENDING, FIXED, LEFT, LEGACY_THEME, MOVING, RIGHT, YCLOUD_THEME } from './constants';
|
|
4
|
+
declare type HeaderData<T> = T & {
|
|
5
|
+
headerIndex?: number;
|
|
6
|
+
};
|
|
7
|
+
declare type FooterData<T> = T & {
|
|
8
|
+
footerIndex?: number;
|
|
9
|
+
};
|
|
10
|
+
export interface DataTableProps<T> {
|
|
11
|
+
columns: Column<T>[];
|
|
12
|
+
headerData?: HeaderData<T>[];
|
|
13
|
+
data: T[];
|
|
14
|
+
footerData?: FooterData<T>[];
|
|
15
|
+
startIndex?: number;
|
|
16
|
+
settings?: Settings;
|
|
17
|
+
emptyDataMessage?: string;
|
|
18
|
+
rowClassName?: (row: T, index: number, isFooterData?: boolean, isHeaderData?: boolean) => string;
|
|
19
|
+
renderEmptyRow?: (columns: DataTableProps<T>['columns']) => React.ReactNode;
|
|
20
|
+
rowKey?: (row: T, index: number) => string | number;
|
|
21
|
+
visibleRowIndex?: (row: T, index: number) => number;
|
|
22
|
+
initialSortOrder?: SortOrder | SortOrder[];
|
|
23
|
+
sortOrder?: SortOrder | SortOrder[];
|
|
24
|
+
theme: THEMES | string;
|
|
25
|
+
onSort?: (sortOrder: DataTableProps<T>['initialSortOrder']) => void;
|
|
26
|
+
onRowClick?: (row: T, index: number, event: React.MouseEvent<HTMLTableRowElement>) => void;
|
|
27
|
+
onError?: (error: unknown) => void;
|
|
28
|
+
nullBeforeNumbers?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface Column<T> {
|
|
31
|
+
name: string;
|
|
32
|
+
header?: React.ReactNode;
|
|
33
|
+
headerTitle?: string;
|
|
34
|
+
className?: string;
|
|
35
|
+
width?: number | string;
|
|
36
|
+
align?: AlignType;
|
|
37
|
+
accessor?: string | ((row: T) => any);
|
|
38
|
+
title?: string | ((row: T) => string);
|
|
39
|
+
render?: (props: {
|
|
40
|
+
value?: unknown;
|
|
41
|
+
row: T;
|
|
42
|
+
index: number;
|
|
43
|
+
footer?: boolean;
|
|
44
|
+
headerData?: boolean;
|
|
45
|
+
}) => React.ReactNode;
|
|
46
|
+
customStyle?: (props: CustomStyleParams<T>) => React.CSSProperties;
|
|
47
|
+
onClick?: (data: {
|
|
48
|
+
row: T;
|
|
49
|
+
index: number;
|
|
50
|
+
footer?: boolean;
|
|
51
|
+
headerData?: boolean;
|
|
52
|
+
}, column: Column<T>) => void;
|
|
53
|
+
sortable?: boolean;
|
|
54
|
+
defaultOrder?: OrderType;
|
|
55
|
+
sortAccessor?: string | ((row: T) => any);
|
|
56
|
+
sortAscending?: Comparator<T>;
|
|
57
|
+
sub?: Column<T>[];
|
|
58
|
+
group?: boolean;
|
|
59
|
+
autogroup?: boolean;
|
|
60
|
+
}
|
|
61
|
+
export declare type DynamicInnerRefT = ReactList;
|
|
62
|
+
export interface Settings {
|
|
63
|
+
displayIndices?: boolean;
|
|
64
|
+
stickyHead?: HeadPosition;
|
|
65
|
+
stickyTop?: 'auto' | number;
|
|
66
|
+
syncHeadOnResize?: boolean;
|
|
67
|
+
stickyFooter?: HeadPosition;
|
|
68
|
+
stickyBottom?: 'auto' | number;
|
|
69
|
+
dynamicRender?: boolean;
|
|
70
|
+
dynamicInnerRef?: React.Ref<DynamicInnerRefT>;
|
|
71
|
+
dynamicRenderType?: 'simple' | 'uniform' | 'variable';
|
|
72
|
+
dynamicItemSizeEstimator?: ReactList['props']['itemSizeEstimator'];
|
|
73
|
+
dynamicItemSizeGetter?: ReactList['props']['itemSizeGetter'];
|
|
74
|
+
dynamicRenderMinSize?: number;
|
|
75
|
+
dynamicRenderUseStaticSize?: boolean;
|
|
76
|
+
dynamicRenderThreshold?: number;
|
|
77
|
+
dynamicRenderScrollParentGetter?: ReactList['props']['scrollParentGetter'];
|
|
78
|
+
dynamicRenderScrollParentViewportSizeGetter?: () => number;
|
|
79
|
+
sortable?: boolean;
|
|
80
|
+
externalSort?: boolean;
|
|
81
|
+
disableSortReset?: boolean;
|
|
82
|
+
defaultOrder?: OrderType;
|
|
83
|
+
highlightRows?: boolean;
|
|
84
|
+
stripedRows?: boolean;
|
|
85
|
+
headerMod?: 'multiline' | 'pre';
|
|
86
|
+
}
|
|
87
|
+
export interface CustomStyleParams<T> {
|
|
88
|
+
row?: T;
|
|
89
|
+
index?: number;
|
|
90
|
+
name: string;
|
|
91
|
+
header?: boolean;
|
|
92
|
+
footer?: boolean;
|
|
93
|
+
headerData?: boolean;
|
|
94
|
+
}
|
|
95
|
+
export declare type AlignType = typeof LEFT | typeof RIGHT | typeof CENTER;
|
|
96
|
+
export declare type OrderType = typeof ASCENDING | typeof DESCENDING;
|
|
97
|
+
export interface SortOrder {
|
|
98
|
+
columnId: string;
|
|
99
|
+
order: OrderType;
|
|
100
|
+
}
|
|
101
|
+
export declare type HeadPosition = typeof FIXED | typeof MOVING;
|
|
102
|
+
export declare type THEMES = typeof LEGACY_THEME | typeof YCLOUD_THEME;
|
|
103
|
+
export interface SortedDataItem<T> {
|
|
104
|
+
row: T;
|
|
105
|
+
index: number;
|
|
106
|
+
span?: {
|
|
107
|
+
[colName: string]: number;
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
export declare type Comparator<T> = (l: SortedDataItem<T>, r: SortedDataItem<T>) => number;
|
|
111
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ColumnExtended, NameToOrderTypeMap, SortOrderWithSortColumns } from './DataTable';
|
|
2
|
+
import { OrderType, Settings, SortOrder, SortedDataItem } from './types';
|
|
3
|
+
export declare type SlimColumn = {
|
|
4
|
+
name: string;
|
|
5
|
+
defaultOrder?: OrderType;
|
|
6
|
+
};
|
|
7
|
+
export declare function getSortOrder({ name: columnName, defaultOrder: columnDefaultOrder }: SlimColumn, { sortOrder, sortColumns }: Partial<SortOrderWithSortColumns>, multiColumnSort?: boolean, { defaultOrder: settingsDefaultOrder, disableSortReset, }?: {
|
|
8
|
+
defaultOrder?: OrderType;
|
|
9
|
+
disableSortReset?: boolean;
|
|
10
|
+
}): {
|
|
11
|
+
sortOrder: NameToOrderTypeMap;
|
|
12
|
+
sortColumns: string[];
|
|
13
|
+
};
|
|
14
|
+
interface SortingFunctionFlags {
|
|
15
|
+
nullBeforeNumbers?: boolean;
|
|
16
|
+
externalSort?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function getSortedData<T>(data: T[], dataColumns: ColumnExtended<T>[], { sortOrder, sortColumns }: SortOrderWithSortColumns, sortingFunctionFlags: SortingFunctionFlags): SortedDataItem<T>[];
|
|
19
|
+
declare type ExternalSortOrderType = SortOrder | SortOrder[];
|
|
20
|
+
export declare function externalToInternalSortOrder(columns: ExternalSortOrderType, settings?: Settings): {
|
|
21
|
+
sortOrder: NameToOrderTypeMap;
|
|
22
|
+
sortColumns: string[];
|
|
23
|
+
};
|
|
24
|
+
export declare function internalToExternalSortOrder(sortOrder: NameToOrderTypeMap): {
|
|
25
|
+
columnId: string;
|
|
26
|
+
order: OrderType;
|
|
27
|
+
}[];
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { __rest } from "tslib";
|
|
2
|
+
import { ASCENDING, DESCENDING } from './constants';
|
|
3
|
+
export function getSortOrder({ name: columnName, defaultOrder: columnDefaultOrder }, { sortOrder = {}, sortColumns = [] }, multiColumnSort = false, { defaultOrder: settingsDefaultOrder, disableSortReset, } = {}) {
|
|
4
|
+
const defaultOrder = columnDefaultOrder || settingsDefaultOrder;
|
|
5
|
+
const emptyResult = {
|
|
6
|
+
sortOrder: {},
|
|
7
|
+
sortColumns: [],
|
|
8
|
+
};
|
|
9
|
+
if (!columnName) {
|
|
10
|
+
return multiColumnSort ? { sortOrder, sortColumns } : emptyResult;
|
|
11
|
+
}
|
|
12
|
+
let newColumns = sortColumns;
|
|
13
|
+
const prevOrder = sortOrder[columnName];
|
|
14
|
+
let order = defaultOrder;
|
|
15
|
+
if (prevOrder) {
|
|
16
|
+
if (prevOrder === defaultOrder || disableSortReset) {
|
|
17
|
+
order = prevOrder === ASCENDING ? DESCENDING : ASCENDING;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
// reset sort order if previously was set non-default
|
|
21
|
+
order = undefined;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (!multiColumnSort) {
|
|
25
|
+
return order
|
|
26
|
+
? {
|
|
27
|
+
sortOrder: { [columnName]: order },
|
|
28
|
+
sortColumns: [columnName],
|
|
29
|
+
}
|
|
30
|
+
: emptyResult;
|
|
31
|
+
}
|
|
32
|
+
const _a = sortOrder, _b = columnName, _ = _a[_b], newOrder = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]); // eslint-disable-line no-unused-vars
|
|
33
|
+
if (order) {
|
|
34
|
+
newOrder[columnName] = order;
|
|
35
|
+
if (!new Set(sortColumns).has(columnName)) {
|
|
36
|
+
newColumns = [...sortColumns, columnName];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
newColumns = sortColumns.filter((name) => name !== columnName);
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
sortOrder: newOrder,
|
|
44
|
+
sortColumns: newColumns,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function generateSortingFunction(column, order, flags = {}) {
|
|
48
|
+
const compareValue = order;
|
|
49
|
+
const { sortAscending } = column;
|
|
50
|
+
if (typeof sortAscending === 'function') {
|
|
51
|
+
return (row1, row2) => {
|
|
52
|
+
return compareValue * sortAscending(row1, row2);
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return (row1, row2) => {
|
|
56
|
+
const value1 = column._getSortValue(row1.row);
|
|
57
|
+
const value2 = column._getSortValue(row2.row);
|
|
58
|
+
/* eslint-disable no-eq-null, eqeqeq */
|
|
59
|
+
// Comparison with null made here intentionally
|
|
60
|
+
// to exclude multiple comparison with undefined and null
|
|
61
|
+
if (value1 == null && value2 != null) {
|
|
62
|
+
return flags.nullBeforeNumbers ? -compareValue : 1;
|
|
63
|
+
}
|
|
64
|
+
if (value2 == null && value1 != null) {
|
|
65
|
+
return flags.nullBeforeNumbers ? compareValue : -1;
|
|
66
|
+
}
|
|
67
|
+
/* eslint-enable no-eq-null, eqeqeq */
|
|
68
|
+
if (value1 < value2) {
|
|
69
|
+
return Number(-compareValue);
|
|
70
|
+
}
|
|
71
|
+
if (value1 > value2) {
|
|
72
|
+
return Number(compareValue);
|
|
73
|
+
}
|
|
74
|
+
return 0;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
export function getSortedData(data, dataColumns, { sortOrder, sortColumns }, sortingFunctionFlags) {
|
|
78
|
+
const sortFunctionDict = {};
|
|
79
|
+
dataColumns.forEach((column) => {
|
|
80
|
+
if (sortOrder[column.name]) {
|
|
81
|
+
sortFunctionDict[column.name] = generateSortingFunction(column, sortOrder[column.name], sortingFunctionFlags);
|
|
82
|
+
}
|
|
83
|
+
else if (column.group && column.autogroup) {
|
|
84
|
+
sortFunctionDict[column.name] = generateSortingFunction(column, ASCENDING, sortingFunctionFlags);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
const groupColumns = dataColumns.filter((column) => column.group);
|
|
88
|
+
const hasGroupColumns = groupColumns.length > 0;
|
|
89
|
+
// primarily sort data by group columns, then by user sort
|
|
90
|
+
const sortFunctions = [
|
|
91
|
+
...groupColumns.map((column) => sortFunctionDict[column.name]).filter(Boolean),
|
|
92
|
+
...sortColumns.map((name) => sortFunctionDict[name]).filter(Boolean),
|
|
93
|
+
];
|
|
94
|
+
// add 'span' map into data for grouping purposes
|
|
95
|
+
const indexedData = data.map((row, index) => hasGroupColumns ? { row, index, span: {} } : { row, index });
|
|
96
|
+
if (sortFunctions.length && !sortingFunctionFlags.externalSort) {
|
|
97
|
+
indexedData.sort((row1, row2) => {
|
|
98
|
+
let comparison = 0;
|
|
99
|
+
sortFunctions.some((sort) => {
|
|
100
|
+
comparison = sort(row1, row2);
|
|
101
|
+
return Boolean(comparison);
|
|
102
|
+
});
|
|
103
|
+
return comparison || row1.index - row2.index;
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
// calculate grouping
|
|
107
|
+
if (indexedData.length > 1 && hasGroupColumns) {
|
|
108
|
+
const baseRows = [];
|
|
109
|
+
const baseValues = [];
|
|
110
|
+
indexedData.forEach((row) => {
|
|
111
|
+
groupColumns.every((column, index) => {
|
|
112
|
+
const value = column._getValue(row.row);
|
|
113
|
+
if (baseRows[index] && value === baseValues[index]) {
|
|
114
|
+
baseRows[index].span[column.name] += 1;
|
|
115
|
+
row.span[column.name] = 0;
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
// when column value changed we have to reset not only this column base row,
|
|
120
|
+
// but base rows for all rest columns
|
|
121
|
+
groupColumns.slice(index).forEach((aColumn, aIndex) => {
|
|
122
|
+
baseRows[index + aIndex] = row;
|
|
123
|
+
baseValues[index + aIndex] = aColumn._getValue(row.row);
|
|
124
|
+
row.span[aColumn.name] = 1;
|
|
125
|
+
});
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return indexedData;
|
|
132
|
+
}
|
|
133
|
+
export function externalToInternalSortOrder(columns, settings) {
|
|
134
|
+
const columnList = Array.isArray(columns) ? columns : [columns];
|
|
135
|
+
return columnList.reduce((result, { columnId, order }) => {
|
|
136
|
+
return getSortOrder({ name: columnId, defaultOrder: order }, result, true, settings);
|
|
137
|
+
}, { sortOrder: {}, sortColumns: [] });
|
|
138
|
+
}
|
|
139
|
+
export function internalToExternalSortOrder(sortOrder) {
|
|
140
|
+
return Object.keys(sortOrder).map((columnId) => {
|
|
141
|
+
return {
|
|
142
|
+
columnId,
|
|
143
|
+
order: sortOrder[columnId],
|
|
144
|
+
};
|
|
145
|
+
});
|
|
146
|
+
}
|