@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.
Files changed (58) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/constants.js +1 -26
  3. package/build/constants.js.map +1 -1
  4. package/build/dataviews.js +2 -1
  5. package/build/dataviews.js.map +1 -1
  6. package/build/filter-and-sort-data-view.js +72 -65
  7. package/build/filter-and-sort-data-view.js.map +1 -1
  8. package/build/index.js +2 -2
  9. package/build/index.js.map +1 -1
  10. package/build/layouts.js +38 -0
  11. package/build/layouts.js.map +1 -0
  12. package/build/normalize-fields.js +7 -2
  13. package/build/normalize-fields.js.map +1 -1
  14. package/build/types.js +6 -0
  15. package/build/types.js.map +1 -0
  16. package/build/view-actions.js +2 -1
  17. package/build/view-actions.js.map +1 -1
  18. package/build-module/constants.js +1 -25
  19. package/build-module/constants.js.map +1 -1
  20. package/build-module/dataviews.js +2 -1
  21. package/build-module/dataviews.js.map +1 -1
  22. package/build-module/filter-and-sort-data-view.js +72 -65
  23. package/build-module/filter-and-sort-data-view.js.map +1 -1
  24. package/build-module/index.js +1 -1
  25. package/build-module/index.js.map +1 -1
  26. package/build-module/layouts.js +30 -0
  27. package/build-module/layouts.js.map +1 -0
  28. package/build-module/normalize-fields.js +7 -2
  29. package/build-module/normalize-fields.js.map +1 -1
  30. package/build-module/types.js +2 -0
  31. package/build-module/types.js.map +1 -0
  32. package/build-module/view-actions.js +2 -1
  33. package/build-module/view-actions.js.map +1 -1
  34. package/build-style/style-rtl.css +20 -17
  35. package/build-style/style.css +20 -17
  36. package/build-types/constants.d.ts +45 -0
  37. package/build-types/constants.d.ts.map +1 -0
  38. package/build-types/filter-and-sort-data-view.d.ts +18 -0
  39. package/build-types/filter-and-sort-data-view.d.ts.map +1 -0
  40. package/build-types/normalize-fields.d.ts +12 -0
  41. package/build-types/normalize-fields.d.ts.map +1 -0
  42. package/build-types/types.d.ts +122 -0
  43. package/build-types/types.d.ts.map +1 -0
  44. package/package.json +11 -11
  45. package/src/{constants.js → constants.ts} +1 -35
  46. package/src/dataviews.js +2 -1
  47. package/src/filter-and-sort-data-view.ts +164 -0
  48. package/src/index.js +1 -1
  49. package/src/layouts.js +39 -0
  50. package/src/normalize-fields.ts +23 -0
  51. package/src/stories/fixtures.js +0 -2
  52. package/src/style.scss +23 -16
  53. package/src/types.ts +144 -0
  54. package/src/view-actions.js +2 -1
  55. package/tsconfig.json +20 -0
  56. package/tsconfig.tsbuildinfo +1 -0
  57. package/src/filter-and-sort-data-view.js +0 -154
  58. package/src/normalize-fields.js +0 -17
@@ -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: 4px 8px 4px 4px;
378
+ padding: 8px 0 4px;
381
379
  }
382
380
  .dataviews-view-grid .dataviews-view-grid__card .dataviews-view-grid__primary-field {
383
- min-height: 40px;
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: 3px 3px 0 0;
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.0.0",
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.56.0",
33
- "@wordpress/components": "^27.4.0",
34
- "@wordpress/compose": "^6.33.0",
35
- "@wordpress/element": "^5.33.0",
36
- "@wordpress/i18n": "^4.56.0",
37
- "@wordpress/icons": "^9.47.0",
38
- "@wordpress/keycodes": "^3.56.0",
39
- "@wordpress/primitives": "^3.54.0",
40
- "@wordpress/private-apis": "^0.38.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": "280403b4c1cf6cc2c55a6c4d56f9ef91145e4191"
50
+ "gitHead": "581d8a5580dba8f600b7268d51eb554771ae482c"
51
51
  }
@@ -1,20 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
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';
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 { VIEW_LAYOUTS, LAYOUT_TABLE, LAYOUT_GRID } from './constants';
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
@@ -1,3 +1,3 @@
1
1
  export { default as DataViews } from './dataviews';
2
- export { VIEW_LAYOUTS } from './constants';
2
+ export { VIEW_LAYOUTS } from './layouts';
3
3
  export { filterSortAndPaginate } from './filter-and-sort-data-view';
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
+ }
@@ -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' },