@wordpress/dataviews 1.0.0 → 1.1.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/CHANGELOG.md +2 -0
- package/build/constants.js +1 -26
- package/build/constants.js.map +1 -1
- package/build/dataviews.js +2 -1
- package/build/dataviews.js.map +1 -1
- package/build/filter-and-sort-data-view.js +72 -65
- package/build/filter-and-sort-data-view.js.map +1 -1
- package/build/index.js +2 -2
- package/build/index.js.map +1 -1
- package/build/layouts.js +38 -0
- package/build/layouts.js.map +1 -0
- package/build/normalize-fields.js +7 -2
- package/build/normalize-fields.js.map +1 -1
- package/build/types.js +6 -0
- package/build/types.js.map +1 -0
- package/build/view-actions.js +2 -1
- package/build/view-actions.js.map +1 -1
- package/build-module/constants.js +1 -25
- package/build-module/constants.js.map +1 -1
- package/build-module/dataviews.js +2 -1
- package/build-module/dataviews.js.map +1 -1
- package/build-module/filter-and-sort-data-view.js +72 -65
- package/build-module/filter-and-sort-data-view.js.map +1 -1
- package/build-module/index.js +1 -1
- package/build-module/index.js.map +1 -1
- package/build-module/layouts.js +30 -0
- package/build-module/layouts.js.map +1 -0
- package/build-module/normalize-fields.js +7 -2
- package/build-module/normalize-fields.js.map +1 -1
- package/build-module/types.js +2 -0
- package/build-module/types.js.map +1 -0
- package/build-module/view-actions.js +2 -1
- package/build-module/view-actions.js.map +1 -1
- package/build-style/style-rtl.css +20 -17
- package/build-style/style.css +20 -17
- package/build-types/constants.d.ts +45 -0
- package/build-types/constants.d.ts.map +1 -0
- package/build-types/filter-and-sort-data-view.d.ts +18 -0
- package/build-types/filter-and-sort-data-view.d.ts.map +1 -0
- package/build-types/normalize-fields.d.ts +12 -0
- package/build-types/normalize-fields.d.ts.map +1 -0
- package/build-types/types.d.ts +122 -0
- package/build-types/types.d.ts.map +1 -0
- package/package.json +11 -11
- package/src/{constants.js → constants.ts} +1 -35
- package/src/dataviews.js +2 -1
- package/src/filter-and-sort-data-view.ts +164 -0
- package/src/index.js +1 -1
- package/src/layouts.js +39 -0
- package/src/normalize-fields.ts +23 -0
- package/src/stories/fixtures.js +0 -2
- package/src/style.scss +23 -16
- package/src/types.ts +144 -0
- package/src/view-actions.js +2 -1
- package/tsconfig.json +20 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/src/filter-and-sort-data-view.js +0 -154
- package/src/normalize-fields.js +0 -17
package/build-style/style.css
CHANGED
|
@@ -371,37 +371,46 @@
|
|
|
371
371
|
}
|
|
372
372
|
}
|
|
373
373
|
.dataviews-view-grid .dataviews-view-grid__card {
|
|
374
|
-
border-radius: 4px;
|
|
375
|
-
border: 1px solid #e0e0e0;
|
|
376
374
|
height: 100%;
|
|
377
375
|
justify-content: flex-start;
|
|
378
376
|
}
|
|
379
377
|
.dataviews-view-grid .dataviews-view-grid__card .dataviews-view-grid__title-actions {
|
|
380
|
-
padding:
|
|
378
|
+
padding: 8px 0 4px;
|
|
381
379
|
}
|
|
382
380
|
.dataviews-view-grid .dataviews-view-grid__card .dataviews-view-grid__primary-field {
|
|
383
|
-
min-height:
|
|
384
|
-
}
|
|
385
|
-
.dataviews-view-grid .dataviews-view-grid__card.is-selected {
|
|
386
|
-
border-color: var(--wp-admin-theme-color);
|
|
387
|
-
background-color: rgba(var(--wp-admin-theme-color--rgb), 0.04);
|
|
381
|
+
min-height: 32px;
|
|
388
382
|
}
|
|
389
383
|
.dataviews-view-grid .dataviews-view-grid__card.is-selected .dataviews-view-grid__fields .dataviews-view-grid__field .dataviews-view-grid__field-value {
|
|
390
384
|
color: #1e1e1e;
|
|
391
385
|
}
|
|
386
|
+
.dataviews-view-grid .dataviews-view-grid__card.is-selected .page-pages-preview-field__button::after {
|
|
387
|
+
box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color);
|
|
388
|
+
background: rgba(var(--wp-admin-theme-color--rgb), 0.04);
|
|
389
|
+
}
|
|
392
390
|
.dataviews-view-grid .dataviews-view-grid__media {
|
|
393
391
|
width: 100%;
|
|
394
392
|
min-height: 200px;
|
|
395
393
|
aspect-ratio: 1/1;
|
|
396
|
-
border-bottom: 1px solid #e0e0e0;
|
|
397
394
|
background-color: #f0f0f0;
|
|
398
|
-
border-radius:
|
|
395
|
+
border-radius: 4px;
|
|
396
|
+
overflow: hidden;
|
|
397
|
+
position: relative;
|
|
399
398
|
}
|
|
400
399
|
.dataviews-view-grid .dataviews-view-grid__media img {
|
|
401
400
|
object-fit: cover;
|
|
402
401
|
width: 100%;
|
|
403
402
|
height: 100%;
|
|
404
403
|
}
|
|
404
|
+
.dataviews-view-grid .dataviews-view-grid__media::after {
|
|
405
|
+
content: "";
|
|
406
|
+
position: absolute;
|
|
407
|
+
top: 0;
|
|
408
|
+
left: 0;
|
|
409
|
+
width: 100%;
|
|
410
|
+
height: 100%;
|
|
411
|
+
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
|
|
412
|
+
border-radius: 4px;
|
|
413
|
+
}
|
|
405
414
|
.dataviews-view-grid .dataviews-view-grid__fields {
|
|
406
415
|
position: relative;
|
|
407
416
|
font-size: 12px;
|
|
@@ -410,7 +419,6 @@
|
|
|
410
419
|
.dataviews-view-grid .dataviews-view-grid__fields:not(:empty) {
|
|
411
420
|
padding: 12px 0;
|
|
412
421
|
padding-top: 0;
|
|
413
|
-
margin: 0 12px;
|
|
414
422
|
}
|
|
415
423
|
.dataviews-view-grid .dataviews-view-grid__fields .dataviews-view-grid__field {
|
|
416
424
|
align-items: flex-start;
|
|
@@ -431,8 +439,7 @@
|
|
|
431
439
|
color: #757575;
|
|
432
440
|
}
|
|
433
441
|
.dataviews-view-grid .dataviews-view-grid__badge-fields:not(:empty) {
|
|
434
|
-
padding: 12px;
|
|
435
|
-
padding-top: 0;
|
|
442
|
+
padding-bottom: 12px;
|
|
436
443
|
}
|
|
437
444
|
.dataviews-view-grid .dataviews-view-grid__badge-fields .dataviews-view-grid__field-value {
|
|
438
445
|
width: -moz-fit-content;
|
|
@@ -595,10 +602,6 @@
|
|
|
595
602
|
flex-shrink: 0;
|
|
596
603
|
}
|
|
597
604
|
|
|
598
|
-
.dataviews-view-grid__title-actions .dataviews-view-table-selection-checkbox {
|
|
599
|
-
margin-left: 8px;
|
|
600
|
-
}
|
|
601
|
-
|
|
602
605
|
.dataviews-filter-summary__popover .components-popover__content {
|
|
603
606
|
width: 230px;
|
|
604
607
|
padding: 0;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export declare const OPERATOR_IS = "is";
|
|
2
|
+
export declare const OPERATOR_IS_NOT = "isNot";
|
|
3
|
+
export declare const OPERATOR_IS_ANY = "isAny";
|
|
4
|
+
export declare const OPERATOR_IS_NONE = "isNone";
|
|
5
|
+
export declare const OPERATOR_IS_ALL = "isAll";
|
|
6
|
+
export declare const OPERATOR_IS_NOT_ALL = "isNotAll";
|
|
7
|
+
export declare const ALL_OPERATORS: string[];
|
|
8
|
+
export declare const OPERATORS: {
|
|
9
|
+
is: {
|
|
10
|
+
key: string;
|
|
11
|
+
label: string;
|
|
12
|
+
};
|
|
13
|
+
isNot: {
|
|
14
|
+
key: string;
|
|
15
|
+
label: string;
|
|
16
|
+
};
|
|
17
|
+
isAny: {
|
|
18
|
+
key: string;
|
|
19
|
+
label: string;
|
|
20
|
+
};
|
|
21
|
+
isNone: {
|
|
22
|
+
key: string;
|
|
23
|
+
label: string;
|
|
24
|
+
};
|
|
25
|
+
isAll: {
|
|
26
|
+
key: string;
|
|
27
|
+
label: string;
|
|
28
|
+
};
|
|
29
|
+
isNotAll: {
|
|
30
|
+
key: string;
|
|
31
|
+
label: string;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
export declare const SORTING_DIRECTIONS: {
|
|
35
|
+
asc: {
|
|
36
|
+
label: string;
|
|
37
|
+
};
|
|
38
|
+
desc: {
|
|
39
|
+
label: string;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
export declare const LAYOUT_TABLE = "table";
|
|
43
|
+
export declare const LAYOUT_GRID = "grid";
|
|
44
|
+
export declare const LAYOUT_LIST = "list";
|
|
45
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,WAAW,OAAO,CAAC;AAChC,eAAO,MAAM,eAAe,UAAU,CAAC;AACvC,eAAO,MAAM,eAAe,UAAU,CAAC;AACvC,eAAO,MAAM,gBAAgB,WAAW,CAAC;AACzC,eAAO,MAAM,eAAe,UAAU,CAAC;AACvC,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAE9C,eAAO,MAAM,aAAa,UAOzB,CAAC;AACF,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;CAyBrB,CAAC;AAGF,eAAO,MAAM,kBAAkB;;;;;;;CAG9B,CAAC;AAGF,eAAO,MAAM,YAAY,UAAU,CAAC;AACpC,eAAO,MAAM,WAAW,SAAS,CAAC;AAClC,eAAO,MAAM,WAAW,SAAS,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Data, Field, View } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Applies the filtering, sorting and pagination to the raw data based on the view configuration.
|
|
4
|
+
*
|
|
5
|
+
* @param data Raw data.
|
|
6
|
+
* @param view View config.
|
|
7
|
+
* @param fields Fields config.
|
|
8
|
+
*
|
|
9
|
+
* @return Filtered, sorted and paginated data.
|
|
10
|
+
*/
|
|
11
|
+
export declare function filterSortAndPaginate(data: Data, view: View, fields: Field[]): {
|
|
12
|
+
data: Data;
|
|
13
|
+
paginationInfo: {
|
|
14
|
+
totalItems: number;
|
|
15
|
+
totalPages: number;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=filter-and-sort-data-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter-and-sort-data-view.d.ts","sourceRoot":"","sources":["../src/filter-and-sort-data-view.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAQjD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACpC,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,KAAK,EAAE,GACb;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,cAAc,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CA6H5E"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal dependencies
|
|
3
|
+
*/
|
|
4
|
+
import type { Field, NormalizedField } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* Apply default values and normalize the fields config.
|
|
7
|
+
*
|
|
8
|
+
* @param fields Fields config.
|
|
9
|
+
* @return Normalized fields config.
|
|
10
|
+
*/
|
|
11
|
+
export declare function normalizeFields(fields: Field[]): NormalizedField[];
|
|
12
|
+
//# sourceMappingURL=normalize-fields.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-fields.d.ts","sourceRoot":"","sources":["../src/normalize-fields.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAEtD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAE,MAAM,EAAE,KAAK,EAAE,GAAI,eAAe,EAAE,CAWpE"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import type { ReactNode } from 'react';
|
|
5
|
+
type Item = Record<string, any>;
|
|
6
|
+
interface Option {
|
|
7
|
+
value: any;
|
|
8
|
+
label: string;
|
|
9
|
+
}
|
|
10
|
+
interface filterByConfig {
|
|
11
|
+
operators?: Operator[];
|
|
12
|
+
isPrimary?: boolean;
|
|
13
|
+
}
|
|
14
|
+
type Operator = 'is' | 'isNot' | 'isAny' | 'isNone' | 'isAll' | 'isNotAll';
|
|
15
|
+
export interface Field {
|
|
16
|
+
/**
|
|
17
|
+
* The unique identifier of the field.
|
|
18
|
+
*/
|
|
19
|
+
id: string;
|
|
20
|
+
/**
|
|
21
|
+
* The label of the field. Defaults to the id.
|
|
22
|
+
*/
|
|
23
|
+
header?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Callback used to retrieve the value of the field from the item.
|
|
26
|
+
* Defaults to `item[ field.id ]`.
|
|
27
|
+
*/
|
|
28
|
+
getValue?: ({ item }: {
|
|
29
|
+
item: Item;
|
|
30
|
+
}) => any;
|
|
31
|
+
/**
|
|
32
|
+
* Callback used to render the field. Defaults to `field.getValue`.
|
|
33
|
+
*/
|
|
34
|
+
render?: ({ item }: {
|
|
35
|
+
item: Item;
|
|
36
|
+
}) => ReactNode;
|
|
37
|
+
/**
|
|
38
|
+
* The width of the field column.
|
|
39
|
+
*/
|
|
40
|
+
width: string | number | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* The minimum width of the field column.
|
|
43
|
+
*/
|
|
44
|
+
maxWidth: string | number | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* The maximum width of the field column.
|
|
47
|
+
*/
|
|
48
|
+
minWidth: string | number | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Whether the field is sortable.
|
|
51
|
+
*/
|
|
52
|
+
enableSorting: boolean | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* Whether the field is searchable.
|
|
55
|
+
*/
|
|
56
|
+
enableGlobalSearch: boolean | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Whether the field is filterable.
|
|
59
|
+
*/
|
|
60
|
+
enableHiding: boolean | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* The list of options to pick from when using the field as a filter.
|
|
63
|
+
*/
|
|
64
|
+
elements: Option[] | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Filter config for the field.
|
|
67
|
+
*/
|
|
68
|
+
filterBy: filterByConfig | undefined;
|
|
69
|
+
}
|
|
70
|
+
export type NormalizedField = Required<Field>;
|
|
71
|
+
export type Data = Item[];
|
|
72
|
+
export interface Filter {
|
|
73
|
+
/**
|
|
74
|
+
* The field to filter by.
|
|
75
|
+
*/
|
|
76
|
+
field: string;
|
|
77
|
+
/**
|
|
78
|
+
* The operator to use.
|
|
79
|
+
*/
|
|
80
|
+
operator: Operator;
|
|
81
|
+
/**
|
|
82
|
+
* The value to filter by.
|
|
83
|
+
*/
|
|
84
|
+
value: any;
|
|
85
|
+
}
|
|
86
|
+
export interface View {
|
|
87
|
+
/**
|
|
88
|
+
* The layout of the view.
|
|
89
|
+
*/
|
|
90
|
+
type: string;
|
|
91
|
+
/**
|
|
92
|
+
* The global search term.
|
|
93
|
+
*/
|
|
94
|
+
search?: string;
|
|
95
|
+
/**
|
|
96
|
+
* The filters to apply.
|
|
97
|
+
*/
|
|
98
|
+
filters: Filter[];
|
|
99
|
+
/**
|
|
100
|
+
* The sorting configuration.
|
|
101
|
+
*/
|
|
102
|
+
sort?: {
|
|
103
|
+
/**
|
|
104
|
+
* The field to sort by.
|
|
105
|
+
*/
|
|
106
|
+
field: string;
|
|
107
|
+
/**
|
|
108
|
+
* The direction to sort by.
|
|
109
|
+
*/
|
|
110
|
+
direction: string;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* The active page
|
|
114
|
+
*/
|
|
115
|
+
page?: number;
|
|
116
|
+
/**
|
|
117
|
+
* The number of items per page
|
|
118
|
+
*/
|
|
119
|
+
perPage?: number;
|
|
120
|
+
}
|
|
121
|
+
export {};
|
|
122
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,KAAK,IAAI,GAAG,MAAM,CAAE,MAAM,EAAE,GAAG,CAAE,CAAC;AAElC,UAAU,MAAM;IACf,KAAK,EAAE,GAAG,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACd;AAED,UAAU,cAAc;IACvB,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,KAAK,QAAQ,GAAG,IAAI,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;AAE3E,MAAM,WAAW,KAAK;IACrB;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAE,EAAE,IAAI,EAAE,EAAE;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,KAAM,GAAG,CAAC;IAE/C;;OAEG;IACH,MAAM,CAAC,EAAE,CAAE,EAAE,IAAI,EAAE,EAAE;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,KAAM,SAAS,CAAC;IAEnD;;OAEG;IACH,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAEnC;;OAEG;IACH,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAEtC;;OAEG;IACH,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAEtC;;OAEG;IACH,aAAa,EAAE,OAAO,GAAG,SAAS,CAAC;IAEnC;;OAEG;IACH,kBAAkB,EAAE,OAAO,GAAG,SAAS,CAAC;IAExC;;OAEG;IACH,YAAY,EAAE,OAAO,GAAG,SAAS,CAAC;IAElC;;OAEG;IACH,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAE/B;;OAEG;IACH,QAAQ,EAAE,cAAc,GAAG,SAAS,CAAC;CACrC;AAED,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAE,KAAK,CAAE,CAAC;AAEhD,MAAM,MAAM,IAAI,GAAG,IAAI,EAAE,CAAC;AAE1B,MAAM,WAAW,MAAM;IACtB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,QAAQ,EAAE,QAAQ,CAAC;IAEnB;;OAEG;IACH,KAAK,EAAE,GAAG,CAAC;CACX;AAED,MAAM,WAAW,IAAI;IACpB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;IAElB;;OAEG;IACH,IAAI,CAAC,EAAE;QACN;;WAEG;QACH,KAAK,EAAE,MAAM,CAAC;QAEd;;WAEG;QACH,SAAS,EAAE,MAAM,CAAC;KAClB,CAAC;IAEF;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/dataviews",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -29,15 +29,15 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@ariakit/react": "^0.3.12",
|
|
31
31
|
"@babel/runtime": "^7.16.0",
|
|
32
|
-
"@wordpress/a11y": "^3.
|
|
33
|
-
"@wordpress/components": "^27.
|
|
34
|
-
"@wordpress/compose": "^6.
|
|
35
|
-
"@wordpress/element": "^5.
|
|
36
|
-
"@wordpress/i18n": "^4.
|
|
37
|
-
"@wordpress/icons": "^9.
|
|
38
|
-
"@wordpress/keycodes": "^3.
|
|
39
|
-
"@wordpress/primitives": "^3.
|
|
40
|
-
"@wordpress/private-apis": "^0.
|
|
32
|
+
"@wordpress/a11y": "^3.57.0",
|
|
33
|
+
"@wordpress/components": "^27.5.0",
|
|
34
|
+
"@wordpress/compose": "^6.34.0",
|
|
35
|
+
"@wordpress/element": "^5.34.0",
|
|
36
|
+
"@wordpress/i18n": "^4.57.0",
|
|
37
|
+
"@wordpress/icons": "^9.48.0",
|
|
38
|
+
"@wordpress/keycodes": "^3.57.0",
|
|
39
|
+
"@wordpress/primitives": "^3.55.0",
|
|
40
|
+
"@wordpress/private-apis": "^0.39.0",
|
|
41
41
|
"classnames": "^2.3.1",
|
|
42
42
|
"remove-accents": "^0.5.0"
|
|
43
43
|
},
|
|
@@ -47,5 +47,5 @@
|
|
|
47
47
|
"publishConfig": {
|
|
48
48
|
"access": "public"
|
|
49
49
|
},
|
|
50
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "581d8a5580dba8f600b7268d51eb554771ae482c"
|
|
51
51
|
}
|
|
@@ -1,20 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { __
|
|
5
|
-
import {
|
|
6
|
-
blockTable,
|
|
7
|
-
category,
|
|
8
|
-
formatListBullets,
|
|
9
|
-
formatListBulletsRTL,
|
|
10
|
-
} from '@wordpress/icons';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Internal dependencies
|
|
14
|
-
*/
|
|
15
|
-
import ViewTable from './view-table';
|
|
16
|
-
import ViewGrid from './view-grid';
|
|
17
|
-
import ViewList from './view-list';
|
|
4
|
+
import { __ } from '@wordpress/i18n';
|
|
18
5
|
|
|
19
6
|
// Filter operators.
|
|
20
7
|
export const OPERATOR_IS = 'is';
|
|
@@ -69,24 +56,3 @@ export const SORTING_DIRECTIONS = {
|
|
|
69
56
|
export const LAYOUT_TABLE = 'table';
|
|
70
57
|
export const LAYOUT_GRID = 'grid';
|
|
71
58
|
export const LAYOUT_LIST = 'list';
|
|
72
|
-
|
|
73
|
-
export const VIEW_LAYOUTS = [
|
|
74
|
-
{
|
|
75
|
-
type: LAYOUT_TABLE,
|
|
76
|
-
label: __( 'Table' ),
|
|
77
|
-
component: ViewTable,
|
|
78
|
-
icon: blockTable,
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
type: LAYOUT_GRID,
|
|
82
|
-
label: __( 'Grid' ),
|
|
83
|
-
component: ViewGrid,
|
|
84
|
-
icon: category,
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
type: LAYOUT_LIST,
|
|
88
|
-
label: __( 'List' ),
|
|
89
|
-
component: ViewList,
|
|
90
|
-
icon: isRTL() ? formatListBulletsRTL : formatListBullets,
|
|
91
|
-
},
|
|
92
|
-
];
|
package/src/dataviews.js
CHANGED
|
@@ -11,7 +11,8 @@ import Pagination from './pagination';
|
|
|
11
11
|
import ViewActions from './view-actions';
|
|
12
12
|
import Filters from './filters';
|
|
13
13
|
import Search from './search';
|
|
14
|
-
import {
|
|
14
|
+
import { LAYOUT_TABLE, LAYOUT_GRID } from './constants';
|
|
15
|
+
import { VIEW_LAYOUTS } from './layouts';
|
|
15
16
|
import BulkActions from './bulk-actions';
|
|
16
17
|
import { normalizeFields } from './normalize-fields';
|
|
17
18
|
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import removeAccents from 'remove-accents';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies
|
|
8
|
+
*/
|
|
9
|
+
import {
|
|
10
|
+
OPERATOR_IS,
|
|
11
|
+
OPERATOR_IS_NOT,
|
|
12
|
+
OPERATOR_IS_NONE,
|
|
13
|
+
OPERATOR_IS_ANY,
|
|
14
|
+
OPERATOR_IS_ALL,
|
|
15
|
+
OPERATOR_IS_NOT_ALL,
|
|
16
|
+
} from './constants';
|
|
17
|
+
import { normalizeFields } from './normalize-fields';
|
|
18
|
+
import type { Data, Field, View } from './types';
|
|
19
|
+
|
|
20
|
+
function normalizeSearchInput( input = '' ) {
|
|
21
|
+
return removeAccents( input.trim().toLowerCase() );
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const EMPTY_ARRAY: Data = [];
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Applies the filtering, sorting and pagination to the raw data based on the view configuration.
|
|
28
|
+
*
|
|
29
|
+
* @param data Raw data.
|
|
30
|
+
* @param view View config.
|
|
31
|
+
* @param fields Fields config.
|
|
32
|
+
*
|
|
33
|
+
* @return Filtered, sorted and paginated data.
|
|
34
|
+
*/
|
|
35
|
+
export function filterSortAndPaginate(
|
|
36
|
+
data: Data,
|
|
37
|
+
view: View,
|
|
38
|
+
fields: Field[]
|
|
39
|
+
): { data: Data; paginationInfo: { totalItems: number; totalPages: number } } {
|
|
40
|
+
if ( ! data ) {
|
|
41
|
+
return {
|
|
42
|
+
data: EMPTY_ARRAY,
|
|
43
|
+
paginationInfo: { totalItems: 0, totalPages: 0 },
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const _fields = normalizeFields( fields );
|
|
47
|
+
let filteredData = [ ...data ];
|
|
48
|
+
// Handle global search.
|
|
49
|
+
if ( view.search ) {
|
|
50
|
+
const normalizedSearch = normalizeSearchInput( view.search );
|
|
51
|
+
filteredData = filteredData.filter( ( item ) => {
|
|
52
|
+
return _fields
|
|
53
|
+
.filter( ( field ) => field.enableGlobalSearch )
|
|
54
|
+
.map( ( field ) => {
|
|
55
|
+
return normalizeSearchInput( field.getValue( { item } ) );
|
|
56
|
+
} )
|
|
57
|
+
.some( ( field ) => field.includes( normalizedSearch ) );
|
|
58
|
+
} );
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if ( view.filters.length > 0 ) {
|
|
62
|
+
view.filters.forEach( ( filter ) => {
|
|
63
|
+
const field = _fields.find(
|
|
64
|
+
( _field ) => _field.id === filter.field
|
|
65
|
+
);
|
|
66
|
+
if ( field ) {
|
|
67
|
+
if (
|
|
68
|
+
filter.operator === OPERATOR_IS_ANY &&
|
|
69
|
+
filter?.value?.length > 0
|
|
70
|
+
) {
|
|
71
|
+
filteredData = filteredData.filter( ( item ) => {
|
|
72
|
+
const fieldValue = field.getValue( { item } );
|
|
73
|
+
if ( Array.isArray( fieldValue ) ) {
|
|
74
|
+
return filter.value.some( ( filterValue: any ) =>
|
|
75
|
+
fieldValue.includes( filterValue )
|
|
76
|
+
);
|
|
77
|
+
} else if ( typeof fieldValue === 'string' ) {
|
|
78
|
+
return filter.value.includes( fieldValue );
|
|
79
|
+
}
|
|
80
|
+
return false;
|
|
81
|
+
} );
|
|
82
|
+
} else if (
|
|
83
|
+
filter.operator === OPERATOR_IS_NONE &&
|
|
84
|
+
filter?.value?.length > 0
|
|
85
|
+
) {
|
|
86
|
+
filteredData = filteredData.filter( ( item ) => {
|
|
87
|
+
const fieldValue = field.getValue( { item } );
|
|
88
|
+
if ( Array.isArray( fieldValue ) ) {
|
|
89
|
+
return ! filter.value.some( ( filterValue: any ) =>
|
|
90
|
+
fieldValue.includes( filterValue )
|
|
91
|
+
);
|
|
92
|
+
} else if ( typeof fieldValue === 'string' ) {
|
|
93
|
+
return ! filter.value.includes( fieldValue );
|
|
94
|
+
}
|
|
95
|
+
return false;
|
|
96
|
+
} );
|
|
97
|
+
} else if (
|
|
98
|
+
filter.operator === OPERATOR_IS_ALL &&
|
|
99
|
+
filter?.value?.length > 0
|
|
100
|
+
) {
|
|
101
|
+
filteredData = filteredData.filter( ( item ) => {
|
|
102
|
+
return filter.value.every( ( value: any ) => {
|
|
103
|
+
return field.getValue( { item } ).includes( value );
|
|
104
|
+
} );
|
|
105
|
+
} );
|
|
106
|
+
} else if (
|
|
107
|
+
filter.operator === OPERATOR_IS_NOT_ALL &&
|
|
108
|
+
filter?.value?.length > 0
|
|
109
|
+
) {
|
|
110
|
+
filteredData = filteredData.filter( ( item ) => {
|
|
111
|
+
return filter.value.every( ( value: any ) => {
|
|
112
|
+
return ! field
|
|
113
|
+
.getValue( { item } )
|
|
114
|
+
.includes( value );
|
|
115
|
+
} );
|
|
116
|
+
} );
|
|
117
|
+
} else if ( filter.operator === OPERATOR_IS ) {
|
|
118
|
+
filteredData = filteredData.filter( ( item ) => {
|
|
119
|
+
return filter.value === field.getValue( { item } );
|
|
120
|
+
} );
|
|
121
|
+
} else if ( filter.operator === OPERATOR_IS_NOT ) {
|
|
122
|
+
filteredData = filteredData.filter( ( item ) => {
|
|
123
|
+
return filter.value !== field.getValue( { item } );
|
|
124
|
+
} );
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
} );
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Handle sorting.
|
|
131
|
+
if ( view.sort ) {
|
|
132
|
+
const fieldId = view.sort.field;
|
|
133
|
+
const fieldToSort = _fields.find( ( field ) => {
|
|
134
|
+
return field.id === fieldId;
|
|
135
|
+
} );
|
|
136
|
+
if ( fieldToSort ) {
|
|
137
|
+
filteredData.sort( ( a, b ) => {
|
|
138
|
+
const valueA = fieldToSort.getValue( { item: a } ) ?? '';
|
|
139
|
+
const valueB = fieldToSort.getValue( { item: b } ) ?? '';
|
|
140
|
+
return view.sort?.direction === 'asc'
|
|
141
|
+
? valueA.localeCompare( valueB )
|
|
142
|
+
: valueB.localeCompare( valueA );
|
|
143
|
+
} );
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Handle pagination.
|
|
148
|
+
let totalItems = filteredData.length;
|
|
149
|
+
let totalPages = 1;
|
|
150
|
+
if ( view.page !== undefined && view.perPage !== undefined ) {
|
|
151
|
+
const start = ( view.page - 1 ) * view.perPage;
|
|
152
|
+
totalItems = filteredData?.length || 0;
|
|
153
|
+
totalPages = Math.ceil( totalItems / view.perPage );
|
|
154
|
+
filteredData = filteredData?.slice( start, start + view.perPage );
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
data: filteredData,
|
|
159
|
+
paginationInfo: {
|
|
160
|
+
totalItems,
|
|
161
|
+
totalPages,
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
}
|
package/src/index.js
CHANGED
package/src/layouts.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { __, isRTL } from '@wordpress/i18n';
|
|
5
|
+
import {
|
|
6
|
+
blockTable,
|
|
7
|
+
category,
|
|
8
|
+
formatListBullets,
|
|
9
|
+
formatListBulletsRTL,
|
|
10
|
+
} from '@wordpress/icons';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Internal dependencies
|
|
14
|
+
*/
|
|
15
|
+
import ViewTable from './view-table';
|
|
16
|
+
import ViewGrid from './view-grid';
|
|
17
|
+
import ViewList from './view-list';
|
|
18
|
+
import { LAYOUT_GRID, LAYOUT_LIST, LAYOUT_TABLE } from './constants';
|
|
19
|
+
|
|
20
|
+
export const VIEW_LAYOUTS = [
|
|
21
|
+
{
|
|
22
|
+
type: LAYOUT_TABLE,
|
|
23
|
+
label: __( 'Table' ),
|
|
24
|
+
component: ViewTable,
|
|
25
|
+
icon: blockTable,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
type: LAYOUT_GRID,
|
|
29
|
+
label: __( 'Grid' ),
|
|
30
|
+
component: ViewGrid,
|
|
31
|
+
icon: category,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
type: LAYOUT_LIST,
|
|
35
|
+
label: __( 'List' ),
|
|
36
|
+
component: ViewList,
|
|
37
|
+
icon: isRTL() ? formatListBulletsRTL : formatListBullets,
|
|
38
|
+
},
|
|
39
|
+
];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal dependencies
|
|
3
|
+
*/
|
|
4
|
+
import type { Field, NormalizedField } from './types';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Apply default values and normalize the fields config.
|
|
8
|
+
*
|
|
9
|
+
* @param fields Fields config.
|
|
10
|
+
* @return Normalized fields config.
|
|
11
|
+
*/
|
|
12
|
+
export function normalizeFields( fields: Field[] ): NormalizedField[] {
|
|
13
|
+
return fields.map( ( field ) => {
|
|
14
|
+
const getValue = field.getValue || ( ( { item } ) => item[ field.id ] );
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
...field,
|
|
18
|
+
header: field.header || field.id,
|
|
19
|
+
getValue,
|
|
20
|
+
render: field.render || getValue,
|
|
21
|
+
};
|
|
22
|
+
} );
|
|
23
|
+
}
|
package/src/stories/fixtures.js
CHANGED
|
@@ -171,7 +171,6 @@ export const fields = [
|
|
|
171
171
|
id: 'type',
|
|
172
172
|
maxWidth: 400,
|
|
173
173
|
enableHiding: false,
|
|
174
|
-
type: 'enumeration',
|
|
175
174
|
elements: [
|
|
176
175
|
{ value: 'Not a planet', label: 'Not a planet' },
|
|
177
176
|
{ value: 'Ice giant', label: 'Ice giant' },
|
|
@@ -189,7 +188,6 @@ export const fields = [
|
|
|
189
188
|
{
|
|
190
189
|
header: 'Categories',
|
|
191
190
|
id: 'categories',
|
|
192
|
-
type: 'enumeration',
|
|
193
191
|
elements: [
|
|
194
192
|
{ value: 'Space', label: 'Space' },
|
|
195
193
|
{ value: 'NASA', label: 'NASA' },
|